Add client api support for CA config endpoints

This commit is contained in:
Kyle Havlovitz 2018-05-23 14:44:24 -07:00 committed by Mitchell Hashimoto
parent 5683d628c4
commit 74f225fcd2
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 113 additions and 0 deletions

View File

@ -1,9 +1,44 @@
package api package api
import ( import (
"fmt"
"time" "time"
"github.com/mitchellh/mapstructure"
) )
// CAConfig is the structure for the Connect CA configuration.
type CAConfig struct {
// Provider is the CA provider implementation to use.
Provider string
// Configuration is arbitrary configuration for the provider. This
// should only contain primitive values and containers (such as lists
// and maps).
Config map[string]interface{}
CreateIndex uint64
ModifyIndex uint64
}
// ConsulCAProviderConfig is the config for the built-in Consul CA provider.
type ConsulCAProviderConfig struct {
PrivateKey string
RootCert string
RotationPeriod time.Duration
}
// ParseConsulCAConfig takes a raw config map and returns a parsed
// ConsulCAProviderConfig.
func ParseConsulCAConfig(raw map[string]interface{}) (*ConsulCAProviderConfig, error) {
var config ConsulCAProviderConfig
if err := mapstructure.WeakDecode(raw, &config); err != nil {
return nil, fmt.Errorf("error decoding config: %s", err)
}
return &config, nil
}
// CARootList is the structure for the results of listing roots. // CARootList is the structure for the results of listing roots.
type CARootList struct { type CARootList struct {
ActiveRootID string ActiveRootID string
@ -79,3 +114,40 @@ func (h *Connect) CARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) {
} }
return &out, qm, nil return &out, qm, nil
} }
// CAGetConfig returns the current CA configuration.
func (h *Connect) CAGetConfig(q *QueryOptions) (*CAConfig, *QueryMeta, error) {
r := h.c.newRequest("GET", "/v1/connect/ca/configuration")
r.setQueryOptions(q)
rtt, resp, err := requireOK(h.c.doRequest(r))
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
qm := &QueryMeta{}
parseQueryMeta(resp, qm)
qm.RequestTime = rtt
var out CAConfig
if err := decodeBody(resp, &out); err != nil {
return nil, nil, err
}
return &out, qm, nil
}
// CASetConfig sets the current CA configuration.
func (h *Connect) CASetConfig(conf *CAConfig, q *WriteOptions) (*WriteMeta, error) {
r := h.c.newRequest("PUT", "/v1/connect/ca/configuration")
r.setWriteOptions(q)
r.obj = conf
rtt, resp, err := requireOK(h.c.doRequest(r))
if err != nil {
return nil, err
}
defer resp.Body.Close()
wm := &WriteMeta{}
wm.RequestTime = rtt
return wm, nil
}

View File

@ -2,6 +2,9 @@ package api
import ( import (
"testing" "testing"
"time"
"github.com/pascaldekloe/goe/verify"
"github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil"
"github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/consul/testutil/retry"
@ -51,3 +54,41 @@ func TestAPI_ConnectCARoots_list(t *testing.T) {
}) })
} }
func TestAPI_ConnectCAConfig_get_set(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()
expected := &ConsulCAProviderConfig{
RotationPeriod: 90 * 24 * time.Hour,
}
// This fails occasionally if server doesn't have time to bootstrap CA so
// retry
retry.Run(t, func(r *retry.R) {
connect := c.Connect()
conf, _, err := connect.CAGetConfig(nil)
r.Check(err)
if conf.Provider != "consul" {
r.Fatalf("expected default provider, got %q", conf.Provider)
}
parsed, err := ParseConsulCAConfig(conf.Config)
r.Check(err)
verify.Values(r, "", parsed, expected)
// Change a config value and update
conf.Config["RotationPeriod"] = 120 * 24 * time.Hour
_, err = connect.CASetConfig(conf, nil)
r.Check(err)
updated, _, err := connect.CAGetConfig(nil)
r.Check(err)
expected.RotationPeriod = 120 * 24 * time.Hour
parsed, err = ParseConsulCAConfig(updated.Config)
r.Check(err)
verify.Values(r, "", parsed, expected)
})
}