Support giving the duration as a string in CA config
This commit is contained in:
parent
118aa0f00a
commit
4d46bba2c4
|
@ -1,4 +1,4 @@
|
|||
package connect
|
||||
package ca
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package connect
|
||||
package ca
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/hashicorp/consul/agent/connect"
|
||||
"github.com/hashicorp/consul/agent/consul/state"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
type ConsulProvider struct {
|
||||
|
@ -111,19 +110,6 @@ func NewConsulProvider(rawConfig map[string]interface{}, delegate ConsulProvider
|
|||
return provider, nil
|
||||
}
|
||||
|
||||
func ParseConsulCAConfig(raw map[string]interface{}) (*structs.ConsulCAProviderConfig, error) {
|
||||
var config structs.ConsulCAProviderConfig
|
||||
if err := mapstructure.WeakDecode(raw, &config); err != nil {
|
||||
return nil, fmt.Errorf("error decoding config: %s", err)
|
||||
}
|
||||
|
||||
if config.PrivateKey == "" && config.RootCert != "" {
|
||||
return nil, fmt.Errorf("must provide a private key when providing a root cert")
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// Return the active root CA and generate a new one if needed
|
||||
func (c *ConsulProvider) ActiveRoot() (string, error) {
|
||||
state := c.delegate.State()
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package ca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func ParseConsulCAConfig(raw map[string]interface{}) (*structs.ConsulCAProviderConfig, error) {
|
||||
var config structs.ConsulCAProviderConfig
|
||||
decodeConf := &mapstructure.DecoderConfig{
|
||||
DecodeHook: ParseDurationFunc(),
|
||||
ErrorUnused: true,
|
||||
Result: &config,
|
||||
WeaklyTypedInput: true,
|
||||
}
|
||||
|
||||
decoder, err := mapstructure.NewDecoder(decodeConf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := decoder.Decode(raw); err != nil {
|
||||
return nil, fmt.Errorf("error decoding config: %s", err)
|
||||
}
|
||||
|
||||
if config.PrivateKey == "" && config.RootCert != "" {
|
||||
return nil, fmt.Errorf("must provide a private key when providing a root cert")
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// ParseDurationFunc is a mapstructure hook for decoding a string or
|
||||
// []uint8 into a time.Duration value.
|
||||
func ParseDurationFunc() mapstructure.DecodeHookFunc {
|
||||
uint8ToString := func(bs []uint8) string {
|
||||
b := make([]byte, len(bs))
|
||||
for i, v := range bs {
|
||||
b[i] = byte(v)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
return func(
|
||||
f reflect.Type,
|
||||
t reflect.Type,
|
||||
data interface{}) (interface{}, error) {
|
||||
var v time.Duration
|
||||
if t != reflect.TypeOf(v) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case f.Kind() == reflect.String:
|
||||
if dur, err := time.ParseDuration(data.(string)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
v = dur
|
||||
}
|
||||
return v, nil
|
||||
case f == reflect.SliceOf(reflect.TypeOf(uint8(0))):
|
||||
s := uint8ToString(data.([]uint8))
|
||||
if dur, err := time.ParseDuration(s); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
v = dur
|
||||
}
|
||||
return v, nil
|
||||
default:
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package connect
|
||||
package ca
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -47,6 +47,7 @@ func (s *HTTPServer) ConnectCAConfigurationGet(resp http.ResponseWriter, req *ht
|
|||
|
||||
var reply structs.CAConfiguration
|
||||
err := s.agent.RPC("ConnectCA.ConfigurationGet", &args, &reply)
|
||||
fixupConfig(&reply)
|
||||
return reply, err
|
||||
}
|
||||
|
||||
|
@ -67,3 +68,25 @@ func (s *HTTPServer) ConnectCAConfigurationSet(resp http.ResponseWriter, req *ht
|
|||
err := s.agent.RPC("ConnectCA.ConfigurationSet", &args, &reply)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// A hack to fix up the config types inside of the map[string]interface{}
|
||||
// so that they get formatted correctly during json.Marshal. Without this,
|
||||
// duration values given as text like "24h" end up getting output back
|
||||
// to the user in base64-encoded form.
|
||||
func fixupConfig(conf *structs.CAConfiguration) {
|
||||
if conf.Provider == structs.ConsulCAProvider {
|
||||
if v, ok := conf.Config["RotationPeriod"]; ok {
|
||||
if raw, ok := v.([]uint8); ok {
|
||||
conf.Config["RotationPeriod"] = uint8ToString(raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func uint8ToString(bs []uint8) string {
|
||||
b := make([]byte, len(bs))
|
||||
for i, v := range bs {
|
||||
b[i] = byte(v)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue