Merge PR #9060: Support reading Raft TLS flags from file
This commit is contained in:
parent
7e5d68a73e
commit
378ec869db
|
@ -11,6 +11,7 @@ CHANGES:
|
|||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* cli: Support reading TLS parameters from file for the `vault operator raft join` command. [[GH-9060](https://github.com/hashicorp/vault/pull/9060)]
|
||||
* plugin: Add SDK method, `Sys.ReloadPlugin`, and CLI command, `vault plugin reload`,
|
||||
for reloading plugins. [[GH-8777](https://github.com/hashicorp/vault/pull/8777)]
|
||||
* sdk/framework: Support accepting TypeFloat parameters over the API [[GH-8923](https://github.com/hashicorp/vault/pull/8923)]
|
||||
|
|
|
@ -4,9 +4,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/api"
|
||||
kvbuilder "github.com/hashicorp/vault/internalshared/kv-builder"
|
||||
"github.com/kr/text"
|
||||
|
@ -273,3 +275,20 @@ func humanDurationInt(i interface{}) interface{} {
|
|||
// If we don't know what type it is, just return the original value
|
||||
return i
|
||||
}
|
||||
|
||||
// parseFlagFile accepts a flag value returns the contets of that value. If the
|
||||
// value starts with '@', that indicates the value is a file and its content
|
||||
// should be read and returned. Otherwise, the raw value is returned.
|
||||
func parseFlagFile(raw string) (string, error) {
|
||||
// check if the provided argument should be read from file
|
||||
if len(raw) > 0 && raw[0] == '@' {
|
||||
contents, err := ioutil.ReadFile(raw[1:])
|
||||
if err != nil {
|
||||
return "", errwrap.Wrapf("error reading file: {{err}}", err)
|
||||
}
|
||||
|
||||
return string(contents), nil
|
||||
}
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
|
|
@ -160,3 +160,52 @@ func TestTruncateToSeconds(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseFlagFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
content := "some raw content"
|
||||
tmpFile, err := ioutil.TempFile(os.TempDir(), "TestParseFlagFile")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temporary file: %v", err)
|
||||
}
|
||||
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
if _, err := tmpFile.WriteString(content); err != nil {
|
||||
t.Fatalf("failed to write to temporary file: %v", err)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
value string
|
||||
exp string
|
||||
}{
|
||||
{
|
||||
"",
|
||||
"",
|
||||
},
|
||||
{
|
||||
content,
|
||||
content,
|
||||
},
|
||||
{
|
||||
fmt.Sprintf("@%s", tmpFile.Name()),
|
||||
content,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.value, func(t *testing.T) {
|
||||
content, err := parseFlagFile(tc.value)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error parsing flag value: %v", err)
|
||||
}
|
||||
|
||||
if content != tc.exp {
|
||||
t.Fatalf("expected %s to be %s", content, tc.exp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,15 @@ Usage: vault operator raft join [options] <leader-api-addr>
|
|||
Join the current node as a peer to the Raft cluster by providing the address
|
||||
of the Raft leader node.
|
||||
|
||||
$ vault operator raft join "http://127.0.0.2:8200"
|
||||
$ vault operator raft join "http://127.0.0.2:8200"
|
||||
|
||||
TLS certificate data can also be consumed from a file on disk by prefixing with
|
||||
the "@" symbol. For example:
|
||||
|
||||
$ vault operator raft join "http://127.0.0.2:8200" \
|
||||
-leader-ca-cert=@leader_ca.crt \
|
||||
-leader-client-cert=@leader_client.crt \
|
||||
-leader-client-key=@leader.key
|
||||
|
||||
` + c.Flags().Help()
|
||||
|
||||
|
@ -114,6 +122,24 @@ func (c *OperatorRaftJoinCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
leaderCACert, err := parseFlagFile(c.flagLeaderCACert)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Failed to parse leader CA certificate: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
leaderClientCert, err := parseFlagFile(c.flagLeaderClientCert)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Failed to parse leader client certificate: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
leaderClientKey, err := parseFlagFile(c.flagLeaderClientKey)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Failed to parse leader client key: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
|
@ -122,9 +148,9 @@ func (c *OperatorRaftJoinCommand) Run(args []string) int {
|
|||
|
||||
resp, err := client.Sys().RaftJoin(&api.RaftJoinRequest{
|
||||
LeaderAPIAddr: leaderAPIAddr,
|
||||
LeaderCACert: c.flagLeaderCACert,
|
||||
LeaderClientCert: c.flagLeaderClientCert,
|
||||
LeaderClientKey: c.flagLeaderClientKey,
|
||||
LeaderCACert: leaderCACert,
|
||||
LeaderClientCert: leaderClientCert,
|
||||
LeaderClientKey: leaderClientKey,
|
||||
Retry: c.flagRetry,
|
||||
NonVoter: c.flagNonVoter,
|
||||
})
|
||||
|
@ -139,9 +165,10 @@ func (c *OperatorRaftJoinCommand) Run(args []string) int {
|
|||
return OutputData(c.UI, resp)
|
||||
}
|
||||
|
||||
out := []string{}
|
||||
out = append(out, "Key | Value")
|
||||
out = append(out, fmt.Sprintf("Joined | %t", resp.Joined))
|
||||
out := []string{
|
||||
"Key | Value",
|
||||
fmt.Sprintf("Joined | %t", resp.Joined),
|
||||
}
|
||||
c.UI.Output(tableOutput(out, nil))
|
||||
|
||||
return 0
|
||||
|
|
Loading…
Reference in New Issue