-
Notifications
You must be signed in to change notification settings - Fork 4.1k
/
read.go
135 lines (105 loc) · 2.9 KB
/
read.go
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package command
import (
"context"
"fmt"
"io"
"os"
"strings"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var (
_ cli.Command = (*ReadCommand)(nil)
_ cli.CommandAutocomplete = (*ReadCommand)(nil)
)
type ReadCommand struct {
*BaseCommand
testStdin io.Reader // for tests
}
func (c *ReadCommand) Synopsis() string {
return "Read data and retrieves secrets"
}
func (c *ReadCommand) Help() string {
helpText := `
Usage: vault read [options] PATH
Reads data from Vault at the given path. This can be used to read secrets,
generate dynamic credentials, get configuration details, and more.
Read a secret from the static secrets engine:
$ vault read secret/my-secret
For a full list of examples and paths, please see the documentation that
corresponds to the secrets engine in use.
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}
func (c *ReadCommand) Flags() *FlagSets {
return c.flagSet(FlagSetHTTP | FlagSetOutputField | FlagSetOutputFormat)
}
func (c *ReadCommand) AutocompleteArgs() complete.Predictor {
return c.PredictVaultFiles()
}
func (c *ReadCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *ReadCommand) Run(args []string) int {
f := c.Flags()
if err := f.Parse(args, ParseOptionAllowRawFormat(true)); err != nil {
c.UI.Error(err.Error())
return 1
}
args = f.Args()
switch {
case len(args) < 1:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
return 1
}
client, err := c.Client()
if err != nil {
c.UI.Error(err.Error())
return 2
}
// client.ReadRaw* methods require a manual timeout override
ctx, cancel := context.WithTimeout(context.Background(), client.ClientTimeout())
defer cancel()
// Pull our fake stdin if needed
stdin := (io.Reader)(os.Stdin)
if c.testStdin != nil {
stdin = c.testStdin
}
path := sanitizePath(args[0])
data, err := parseArgsDataStringLists(stdin, args[1:])
if err != nil {
c.UI.Error(fmt.Sprintf("Failed to parse K=V data: %s", err))
return 1
}
if Format(c.UI) != "raw" {
secret, err := client.Logical().ReadWithDataWithContext(ctx, path, data)
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading %s: %s", path, err))
return 2
}
if secret == nil {
c.UI.Error(fmt.Sprintf("No value found at %s", path))
return 2
}
if c.flagField != "" {
return PrintRawField(c.UI, secret, c.flagField)
}
return OutputSecret(c.UI, secret)
}
resp, err := client.Logical().ReadRawWithDataWithContext(ctx, path, data)
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading: %s: %s", path, err))
return 2
}
if resp == nil || resp.Body == nil {
c.UI.Error(fmt.Sprintf("No value found at %s", path))
return 2
}
defer resp.Body.Close()
contents, err := io.ReadAll(resp.Body)
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading: %s: %s", path, err))
return 2
}
return OutputData(c.UI, contents)
}