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"
|
||||
catlistsvc "github.com/hashicorp/consul/command/catalog/list/services"
|
||||
"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/event"
|
||||
"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 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 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("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 })
|
||||
|
|
|
@ -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