Add CA CLI commands for getting/setting config
This commit is contained in:
parent
1a1090aebf
commit
96f4ff961c
|
@ -7,6 +7,9 @@ import (
|
||||||
catlistnodes "github.com/hashicorp/consul/command/catalog/list/nodes"
|
catlistnodes "github.com/hashicorp/consul/command/catalog/list/nodes"
|
||||||
catlistsvc "github.com/hashicorp/consul/command/catalog/list/services"
|
catlistsvc "github.com/hashicorp/consul/command/catalog/list/services"
|
||||||
"github.com/hashicorp/consul/command/connect"
|
"github.com/hashicorp/consul/command/connect"
|
||||||
|
"github.com/hashicorp/consul/command/connect/ca"
|
||||||
|
caget "github.com/hashicorp/consul/command/connect/ca/get"
|
||||||
|
caset "github.com/hashicorp/consul/command/connect/ca/set"
|
||||||
"github.com/hashicorp/consul/command/connect/proxy"
|
"github.com/hashicorp/consul/command/connect/proxy"
|
||||||
"github.com/hashicorp/consul/command/event"
|
"github.com/hashicorp/consul/command/event"
|
||||||
"github.com/hashicorp/consul/command/exec"
|
"github.com/hashicorp/consul/command/exec"
|
||||||
|
@ -67,6 +70,9 @@ func init() {
|
||||||
Register("catalog nodes", func(ui cli.Ui) (cli.Command, error) { return catlistnodes.New(ui), nil })
|
Register("catalog nodes", func(ui cli.Ui) (cli.Command, error) { return catlistnodes.New(ui), nil })
|
||||||
Register("catalog services", func(ui cli.Ui) (cli.Command, error) { return catlistsvc.New(ui), nil })
|
Register("catalog services", func(ui cli.Ui) (cli.Command, error) { return catlistsvc.New(ui), nil })
|
||||||
Register("connect", func(ui cli.Ui) (cli.Command, error) { return connect.New(), nil })
|
Register("connect", func(ui cli.Ui) (cli.Command, error) { return connect.New(), nil })
|
||||||
|
Register("connect ca", func(ui cli.Ui) (cli.Command, error) { return ca.New(), nil })
|
||||||
|
Register("connect ca get-config", func(ui cli.Ui) (cli.Command, error) { return caget.New(ui), nil })
|
||||||
|
Register("connect ca set-config", func(ui cli.Ui) (cli.Command, error) { return caset.New(ui), nil })
|
||||||
Register("connect proxy", func(ui cli.Ui) (cli.Command, error) { return proxy.New(ui, MakeShutdownCh()), nil })
|
Register("connect proxy", func(ui cli.Ui) (cli.Command, error) { return proxy.New(ui, MakeShutdownCh()), nil })
|
||||||
Register("event", func(ui cli.Ui) (cli.Command, error) { return event.New(ui), nil })
|
Register("event", func(ui cli.Ui) (cli.Command, error) { return event.New(ui), nil })
|
||||||
Register("exec", func(ui cli.Ui) (cli.Command, error) { return exec.New(ui, MakeShutdownCh()), nil })
|
Register("exec", func(ui cli.Ui) (cli.Command, error) { return exec.New(ui, MakeShutdownCh()), nil })
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/consul/command/flags"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() *cmd {
|
||||||
|
return &cmd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmd struct{}
|
||||||
|
|
||||||
|
func (c *cmd) Run(args []string) int {
|
||||||
|
return cli.RunResultHelp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Synopsis() string {
|
||||||
|
return synopsis
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Help() string {
|
||||||
|
return flags.Usage(help, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
const synopsis = "Interact with the Consul Connect CA"
|
||||||
|
const help = `
|
||||||
|
Usage: consul connect ca <subcommand> [options] [args]
|
||||||
|
|
||||||
|
This command has subcommands for interacting with Consul Connect's CA.
|
||||||
|
|
||||||
|
Here are some simple examples, and more detailed examples are available
|
||||||
|
in the subcommands or the documentation.
|
||||||
|
|
||||||
|
Get the configuration:
|
||||||
|
|
||||||
|
$ consul connect ca get-config
|
||||||
|
|
||||||
|
Update the configuration:
|
||||||
|
|
||||||
|
$ consul connect ca set-config -config-file ca.json
|
||||||
|
|
||||||
|
For more examples, ask for subcommand help or view the documentation.
|
||||||
|
`
|
|
@ -0,0 +1,13 @@
|
||||||
|
package ca
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCatalogCommand_noTabs(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if strings.ContainsRune(New().Help(), '\t') {
|
||||||
|
t.Fatal("help has tabs")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package get
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/command/flags"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(ui cli.Ui) *cmd {
|
||||||
|
c := &cmd{UI: ui}
|
||||||
|
c.init()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmd struct {
|
||||||
|
UI cli.Ui
|
||||||
|
flags *flag.FlagSet
|
||||||
|
http *flags.HTTPFlags
|
||||||
|
help string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) init() {
|
||||||
|
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
c.http = &flags.HTTPFlags{}
|
||||||
|
flags.Merge(c.flags, c.http.ClientFlags())
|
||||||
|
flags.Merge(c.flags, c.http.ServerFlags())
|
||||||
|
c.help = flags.Usage(help, c.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Run(args []string) int {
|
||||||
|
if err := c.flags.Parse(args); err != nil {
|
||||||
|
if err == flag.ErrHelp {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a client.
|
||||||
|
client, err := c.http.APIClient()
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the current configuration.
|
||||||
|
opts := &api.QueryOptions{
|
||||||
|
AllowStale: c.http.Stale(),
|
||||||
|
}
|
||||||
|
config, _, err := client.Connect().CAGetConfig(opts)
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error querying CA configuration: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
output, err := json.MarshalIndent(config, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error formatting CA configuration: %s", err))
|
||||||
|
}
|
||||||
|
c.UI.Output(string(output))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Synopsis() string {
|
||||||
|
return synopsis
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Help() string {
|
||||||
|
return c.help
|
||||||
|
}
|
||||||
|
|
||||||
|
const synopsis = "Display the current Connect CA configuration"
|
||||||
|
const help = `
|
||||||
|
Usage: consul connect ca get-config [options]
|
||||||
|
|
||||||
|
Displays the current Connect CA configuration.
|
||||||
|
`
|
|
@ -0,0 +1,35 @@
|
||||||
|
package get
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConnectCAGetConfigCommand_noTabs(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
|
||||||
|
t.Fatal("help has tabs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnectCAGetConfigCommand(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a := agent.NewTestAgent(t.Name(), ``)
|
||||||
|
defer a.Shutdown()
|
||||||
|
|
||||||
|
ui := cli.NewMockUi()
|
||||||
|
c := New(ui)
|
||||||
|
args := []string{"-http-addr=" + a.HTTPAddr()}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
output := strings.TrimSpace(ui.OutputWriter.String())
|
||||||
|
if !strings.Contains(output, `"Provider": "consul"`) {
|
||||||
|
t.Fatalf("bad: %s", output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package set
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/command/flags"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(ui cli.Ui) *cmd {
|
||||||
|
c := &cmd{UI: ui}
|
||||||
|
c.init()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmd struct {
|
||||||
|
UI cli.Ui
|
||||||
|
flags *flag.FlagSet
|
||||||
|
http *flags.HTTPFlags
|
||||||
|
help string
|
||||||
|
|
||||||
|
// flags
|
||||||
|
configFile flags.StringValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) init() {
|
||||||
|
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
c.flags.Var(&c.configFile, "config-file",
|
||||||
|
"The path to the config file to use.")
|
||||||
|
|
||||||
|
c.http = &flags.HTTPFlags{}
|
||||||
|
flags.Merge(c.flags, c.http.ClientFlags())
|
||||||
|
flags.Merge(c.flags, c.http.ServerFlags())
|
||||||
|
c.help = flags.Usage(help, c.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Run(args []string) int {
|
||||||
|
if err := c.flags.Parse(args); err != nil {
|
||||||
|
if err == flag.ErrHelp {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
c.UI.Error(fmt.Sprintf("Failed to parse args: %v", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a client.
|
||||||
|
client, err := c.http.APIClient()
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.configFile.String() == "" {
|
||||||
|
c.UI.Error("The -config-file flag is required")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadFile(c.configFile.String())
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error reading config file: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var config api.CAConfig
|
||||||
|
if err := json.Unmarshal(bytes, &config); err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error parsing config file: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new configuration.
|
||||||
|
if _, err := client.Connect().CASetConfig(&config, nil); err != nil {
|
||||||
|
c.UI.Error(fmt.Sprintf("Error setting CA configuration: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
c.UI.Output("Configuration updated!")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Synopsis() string {
|
||||||
|
return synopsis
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) Help() string {
|
||||||
|
return c.help
|
||||||
|
}
|
||||||
|
|
||||||
|
const synopsis = "Modify the current Connect CA configuration"
|
||||||
|
const help = `
|
||||||
|
Usage: consul connect ca set-config [options]
|
||||||
|
|
||||||
|
Modifies the current Connect CA configuration.
|
||||||
|
`
|
|
@ -0,0 +1,51 @@
|
||||||
|
package set
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent"
|
||||||
|
"github.com/hashicorp/consul/agent/connect/ca"
|
||||||
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConnectCASetConfigCommand_noTabs(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
|
||||||
|
t.Fatal("help has tabs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnectCASetConfigCommand(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
require := require.New(t)
|
||||||
|
a := agent.NewTestAgent(t.Name(), ``)
|
||||||
|
defer a.Shutdown()
|
||||||
|
|
||||||
|
ui := cli.NewMockUi()
|
||||||
|
c := New(ui)
|
||||||
|
args := []string{
|
||||||
|
"-http-addr=" + a.HTTPAddr(),
|
||||||
|
"-config-file=test-fixtures/ca_config.json",
|
||||||
|
}
|
||||||
|
|
||||||
|
code := c.Run(args)
|
||||||
|
if code != 0 {
|
||||||
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
req := structs.DCSpecificRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
}
|
||||||
|
var reply structs.CAConfiguration
|
||||||
|
require.NoError(a.RPC("ConnectCA.ConfigurationGet", &req, &reply))
|
||||||
|
require.Equal("consul", reply.Provider)
|
||||||
|
|
||||||
|
parsed, err := ca.ParseConsulCAConfig(reply.Config)
|
||||||
|
require.NoError(err)
|
||||||
|
require.Equal(24*time.Hour, parsed.RotationPeriod)
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Provider": "consul",
|
||||||
|
"Config": {
|
||||||
|
"PrivateKey": "",
|
||||||
|
"RootCert": "",
|
||||||
|
"RotationPeriod": "24h"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue