Skip to content

Commit c1d8950

Browse files
committed
Validate ansible-vault usable
1 parent 4f7e8ad commit c1d8950

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

cmd/dot_env.go

+18
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@ func (c *DotEnvCommand) Run(args []string) int {
4747
}
4848

4949
spinner := NewSpinner(
50+
SpinnerCfg{
51+
Message: "Validating ansible-vault usability",
52+
StopMessage: "ansible-vault is ready to use",
53+
FailMessage: "ansible-vault is not ready to use",
54+
},
55+
)
56+
57+
spinner.Start()
58+
59+
if err := validateAnsibleVaultUsable(c.Trellis.Path); err != nil {
60+
spinner.StopFail()
61+
c.UI.Error(fmt.Sprintf("Error validating ansible-vault usability: %s", err))
62+
return 1
63+
}
64+
65+
spinner.Stop()
66+
67+
spinner = NewSpinner(
5068
SpinnerCfg{
5169
Message: "Generating .env file",
5270
StopMessage: "Generated .env file",

cmd/validate_ansible_vault_usable.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/roots/trellis-cli/command"
9+
"github.com/roots/trellis-cli/trellis"
10+
)
11+
12+
func validateAnsibleVaultUsable(trellisPath string) (err error) {
13+
_, err = command.Cmd("which", []string{"ansible-vault"}).CombinedOutput()
14+
if err != nil {
15+
return fmt.Errorf("command not found: ansible-vault")
16+
}
17+
18+
helpText := "see: https://docs.roots.io/trellis/master/vault/#storing-your-password"
19+
20+
dummyString := "foo bar"
21+
err = command.Cmd("ansible-vault", []string{"encrypt_string", dummyString}).Run()
22+
if err != nil {
23+
return fmt.Errorf("unable to encrypt_string. probably: vault_password_file not exists. %s", helpText)
24+
}
25+
26+
path := findFirstEncryptedFilePath(trellisPath)
27+
if path == "" {
28+
// No encrypted files found. Assume ansible-vault is working.
29+
return nil
30+
}
31+
32+
err = command.Cmd("ansible-vault", []string{"decrypt", "--output", "-", path}).Run()
33+
if err != nil {
34+
return fmt.Errorf("unable to decrypt vault file %s. probably: incorrect vault pass. %s", path, helpText)
35+
}
36+
37+
return nil
38+
}
39+
40+
func findFirstEncryptedFilePath(trellisPath string) string {
41+
defaultVaults := []string{
42+
"group_vars/development/vault.yml", // Start with development because it contains less important secrets.
43+
"group_vars/staging/vault.yml",
44+
"group_vars/all/vault.yml",
45+
"group_vars/production/vault.yml",
46+
}
47+
for _, vault := range defaultVaults {
48+
path := filepath.Join(trellisPath, vault)
49+
50+
isEncrypted, _ := trellis.IsFileEncrypted(path)
51+
if isEncrypted {
52+
return path
53+
}
54+
}
55+
56+
result := ""
57+
filepath.Walk(
58+
filepath.Join(trellisPath, "group_vars"),
59+
func(path string, fi os.FileInfo, _ error) error {
60+
if result != "" {
61+
return nil
62+
}
63+
64+
if fi.IsDir() {
65+
return nil
66+
}
67+
68+
isEncrypted, _ := trellis.IsFileEncrypted(path)
69+
if isEncrypted {
70+
result = path
71+
}
72+
73+
return nil
74+
})
75+
76+
return result
77+
}

0 commit comments

Comments
 (0)