198 lines
5.4 KiB
Go
198 lines
5.4 KiB
Go
|
package ca
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/hashicorp/consul/agent/structs"
|
||
|
"github.com/hashicorp/go-msgpack/codec"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func TestStructs_CAConfiguration_MsgpackEncodeDecode(t *testing.T) {
|
||
|
type testcase struct {
|
||
|
in *structs.CAConfiguration
|
||
|
expectConfig interface{} // provider specific
|
||
|
parseFunc func(*testing.T, map[string]interface{}) interface{}
|
||
|
}
|
||
|
|
||
|
commonBaseMap := map[string]interface{}{
|
||
|
"LeafCertTTL": "30h",
|
||
|
"SkipValidate": true,
|
||
|
"CSRMaxPerSecond": 5.25,
|
||
|
"CSRMaxConcurrent": int64(55),
|
||
|
"PrivateKeyType": "rsa",
|
||
|
"PrivateKeyBits": int64(4096),
|
||
|
}
|
||
|
expectCommonBase := &structs.CommonCAProviderConfig{
|
||
|
LeafCertTTL: 30 * time.Hour,
|
||
|
SkipValidate: true,
|
||
|
CSRMaxPerSecond: 5.25,
|
||
|
CSRMaxConcurrent: 55,
|
||
|
PrivateKeyType: "rsa",
|
||
|
PrivateKeyBits: 4096,
|
||
|
}
|
||
|
|
||
|
cases := map[string]testcase{
|
||
|
structs.ConsulCAProvider: {
|
||
|
in: &structs.CAConfiguration{
|
||
|
ClusterID: "abc",
|
||
|
Provider: structs.ConsulCAProvider,
|
||
|
State: map[string]string{
|
||
|
"foo": "bar",
|
||
|
},
|
||
|
ForceWithoutCrossSigning: true,
|
||
|
RaftIndex: structs.RaftIndex{
|
||
|
CreateIndex: 5,
|
||
|
ModifyIndex: 99,
|
||
|
},
|
||
|
Config: map[string]interface{}{
|
||
|
"PrivateKey": "key",
|
||
|
"RootCert": "cert",
|
||
|
"RotationPeriod": "5m",
|
||
|
"IntermediateCertTTL": "30m",
|
||
|
"DisableCrossSigning": true,
|
||
|
},
|
||
|
},
|
||
|
expectConfig: &structs.ConsulCAProviderConfig{
|
||
|
CommonCAProviderConfig: *expectCommonBase,
|
||
|
PrivateKey: "key",
|
||
|
RootCert: "cert",
|
||
|
RotationPeriod: 5 * time.Minute,
|
||
|
IntermediateCertTTL: 30 * time.Minute,
|
||
|
DisableCrossSigning: true,
|
||
|
},
|
||
|
parseFunc: func(t *testing.T, raw map[string]interface{}) interface{} {
|
||
|
config, err := ParseConsulCAConfig(raw)
|
||
|
require.NoError(t, err)
|
||
|
return config
|
||
|
},
|
||
|
},
|
||
|
structs.VaultCAProvider: {
|
||
|
in: &structs.CAConfiguration{
|
||
|
ClusterID: "abc",
|
||
|
Provider: structs.VaultCAProvider,
|
||
|
State: map[string]string{
|
||
|
"foo": "bar",
|
||
|
},
|
||
|
ForceWithoutCrossSigning: true,
|
||
|
RaftIndex: structs.RaftIndex{
|
||
|
CreateIndex: 5,
|
||
|
ModifyIndex: 99,
|
||
|
},
|
||
|
Config: map[string]interface{}{
|
||
|
"Address": "addr",
|
||
|
"Token": "token",
|
||
|
"RootPKIPath": "root-pki/",
|
||
|
"IntermediatePKIPath": "im-pki/",
|
||
|
"CAFile": "ca-file",
|
||
|
"CAPath": "ca-path",
|
||
|
"CertFile": "cert-file",
|
||
|
"KeyFile": "key-file",
|
||
|
"TLSServerName": "server-name",
|
||
|
"TLSSkipVerify": true,
|
||
|
},
|
||
|
},
|
||
|
expectConfig: &structs.VaultCAProviderConfig{
|
||
|
CommonCAProviderConfig: *expectCommonBase,
|
||
|
Address: "addr",
|
||
|
Token: "token",
|
||
|
RootPKIPath: "root-pki/",
|
||
|
IntermediatePKIPath: "im-pki/",
|
||
|
CAFile: "ca-file",
|
||
|
CAPath: "ca-path",
|
||
|
CertFile: "cert-file",
|
||
|
KeyFile: "key-file",
|
||
|
TLSServerName: "server-name",
|
||
|
TLSSkipVerify: true,
|
||
|
},
|
||
|
parseFunc: func(t *testing.T, raw map[string]interface{}) interface{} {
|
||
|
config, err := ParseVaultCAConfig(raw)
|
||
|
require.NoError(t, err)
|
||
|
return config
|
||
|
},
|
||
|
},
|
||
|
structs.AWSCAProvider: {
|
||
|
in: &structs.CAConfiguration{
|
||
|
ClusterID: "abc",
|
||
|
Provider: structs.AWSCAProvider,
|
||
|
State: map[string]string{
|
||
|
"foo": "bar",
|
||
|
},
|
||
|
ForceWithoutCrossSigning: true,
|
||
|
RaftIndex: structs.RaftIndex{
|
||
|
CreateIndex: 5,
|
||
|
ModifyIndex: 99,
|
||
|
},
|
||
|
Config: map[string]interface{}{
|
||
|
"ExistingARN": "arn://foo",
|
||
|
"DeleteOnExit": true,
|
||
|
},
|
||
|
},
|
||
|
expectConfig: &structs.AWSCAProviderConfig{
|
||
|
CommonCAProviderConfig: *expectCommonBase,
|
||
|
ExistingARN: "arn://foo",
|
||
|
DeleteOnExit: true,
|
||
|
},
|
||
|
parseFunc: func(t *testing.T, raw map[string]interface{}) interface{} {
|
||
|
config, err := ParseAWSCAConfig(raw)
|
||
|
require.NoError(t, err)
|
||
|
return config
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
// underlay common ca config stuff
|
||
|
for _, tc := range cases {
|
||
|
for k, v := range commonBaseMap {
|
||
|
if _, ok := tc.in.Config[k]; !ok {
|
||
|
tc.in.Config[k] = v
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
// This is the common configuration pre-1.7.0
|
||
|
handle1 = structs.TestingOldPre1dot7MsgpackHandle
|
||
|
// This is the common configuration post-1.7.0
|
||
|
handle2 = structs.MsgpackHandle
|
||
|
)
|
||
|
|
||
|
decoderCase := func(t *testing.T, tc testcase, encHandle, decHandle *codec.MsgpackHandle) {
|
||
|
t.Helper()
|
||
|
|
||
|
var buf bytes.Buffer
|
||
|
enc := codec.NewEncoder(&buf, encHandle)
|
||
|
require.NoError(t, enc.Encode(tc.in))
|
||
|
|
||
|
out := &structs.CAConfiguration{}
|
||
|
dec := codec.NewDecoder(&buf, decHandle)
|
||
|
require.NoError(t, dec.Decode(out))
|
||
|
|
||
|
config := tc.parseFunc(t, out.Config)
|
||
|
|
||
|
out.Config = tc.in.Config // no longer care about how this field decoded
|
||
|
require.Equal(t, tc.in, out)
|
||
|
require.Equal(t, tc.expectConfig, config)
|
||
|
// TODO: verify json?
|
||
|
}
|
||
|
|
||
|
for name, tc := range cases {
|
||
|
tc := tc
|
||
|
t.Run(name, func(t *testing.T) {
|
||
|
t.Run("old encoder and old decoder", func(t *testing.T) {
|
||
|
decoderCase(t, tc, handle1, handle1)
|
||
|
})
|
||
|
t.Run("old encoder and new decoder", func(t *testing.T) {
|
||
|
decoderCase(t, tc, handle1, handle2)
|
||
|
})
|
||
|
t.Run("new encoder and old decoder", func(t *testing.T) {
|
||
|
decoderCase(t, tc, handle2, handle1)
|
||
|
})
|
||
|
t.Run("new encoder and new decoder", func(t *testing.T) {
|
||
|
decoderCase(t, tc, handle2, handle2)
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|