1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package cmd
import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/matryer/is"
)
const (
ageIntro = "age-encryption.org/v1"
ageSecretContent = "Super duper secret age text!"
sshSecretContent = "Super duper secret ssh text!"
newAgeSecretContent = "Super duper secret age text!!"
)
func TestGitAge(t *testing.T) {
assert := is.New(t)
gitDir, err := gitBaseDir()
assert.NoErr(err) // Should get git base dir
tmp := t.TempDir()
clone := exec.Command("git", "clone", gitDir, tmp)
clone.Dir = tmp
assert.NoErr(clone.Run()) // Should clone project to temp dir
ageSecretPath := filepath.Join(tmp, "secrets", "age.txt")
assertEncrypted(assert, ageSecretPath) // Age secret should be encrypted before init
sshSecretPath := filepath.Join(tmp, "secrets", "ssh.txt")
assertEncrypted(assert, sshSecretPath) // SSH secret should be encrypted before init
err = os.Chdir(tmp)
assert.NoErr(err) // Should change to temp dir
build := exec.Command("go", "build")
build.Dir = tmp
err = build.Run()
assert.NoErr(err) // Should build git-age
binPath := filepath.Join(tmp, "git-age")
if runtime.GOOS == "windows" {
binPath += ".exe"
}
bin := func(args ...string) error {
c := exec.Command(binPath, args...)
c.Dir = tmp
return c.Run()
}
assertGitCatFileEncrypted(assert) // cat-file should always be encrypted (initial clone)
// Init should do nothing at first
err = bin("init")
assert.NoErr(err) // Should successfully run init
assertEncrypted(assert, ageSecretPath) // Age secret should be encrypted on init without identities
assertEncrypted(assert, sshSecretPath) // SSH secret should be encrypted on init without identities
// Add identities
err = bin("ident", "key.txt")
assert.NoErr(err) // Should add age identity
err = bin("ident", "ssh")
assert.NoErr(err) // Should add ssh identity
// Init should work now
err = bin("init")
assert.NoErr(err) // Should successfully run init
ageContent, err := os.ReadFile(ageSecretPath)
assert.NoErr(err) // Should read age secret file
assert.True(string(ageContent) == ageSecretContent) // Age secret content should match constant
sshContent, err := os.ReadFile(sshSecretPath)
assert.NoErr(err) // Should read ssh secret file
assert.True(string(sshContent) == sshSecretContent) // SSH secret content should match constant
assertGitCatFileEncrypted(assert) // cat-file should always be encrypted (after git-age init)
err = os.WriteFile(ageSecretPath, []byte(newAgeSecretContent), os.ModePerm)
assert.NoErr(err) // Should be able to write the file
git := func(args ...string) error {
args = append([]string{"-c", "user.name=foo", "-c", "user.email=baz@bar.bux", "-c", "commit.gpgsign=false"}, args...)
c := exec.Command("git", args...)
c.Dir = tmp
return c.Run()
}
err = git("add", ageSecretPath)
assert.NoErr(err) // Git add should succeed
err = git("commit", "-m", "feat!: YOLO")
assert.NoErr(err) // Commit should succeed
assertGitCatFileEncrypted(assert) // cat-file should always be encrypted (after commit)
}
func assertGitCatFileEncrypted(t *is.I) {
t.Helper()
out, err := exec.Command("git", "cat-file", "blob", "HEAD:secrets/age.txt").Output()
t.NoErr(err)
t.True(strings.HasPrefix(string(out), ageIntro))
}
func assertEncrypted(t *is.I, fp string) {
t.Helper()
content, err := os.ReadFile(fp)
t.NoErr(err)
t.True(strings.HasPrefix(string(content), ageIntro))
}
|