Move KmsLibrary code to the ent side of config parsing (#13463)

* Move KmsLibrary code to the ent side of config parsing

* Normalize config.go

* Nope, needs to be result
This commit is contained in:
Scott Miller 2021-12-16 14:57:18 -06:00 committed by GitHub
parent 1966264bcd
commit baec515677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 2 additions and 135 deletions

View File

@ -8,13 +8,10 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/hcl"
@ -26,8 +23,6 @@ var entConfigValidate = func(_ *Config, _ string) []configutil.ConfigError {
return nil
}
var kmsLibraryValidator = defaultKmsLibraryValidator
// Config is the configuration for the vault server.
type Config struct {
UnusedKeys configutil.UnusedKeyMap `hcl:",unusedKeyPositions"`
@ -90,8 +85,6 @@ type Config struct {
License string `hcl:"-"`
LicensePath string `hcl:"license_path"`
KmsLibraries map[string]*KMSLibrary `hcl:"-"`
}
const (
@ -109,9 +102,6 @@ func (c *Config) Validate(sourceFilePath string) []configutil.ConfigError {
for _, l := range c.Listeners {
results = append(results, l.Validate(sourceFilePath)...)
}
for _, kmslibrary := range c.KmsLibraries {
results = append(results, kmslibrary.Validate(sourceFilePath)...)
}
results = append(results, c.validateEnt(sourceFilePath)...)
return results
}
@ -181,24 +171,6 @@ func (b *ServiceRegistration) GoString() string {
return fmt.Sprintf("*%#v", *b)
}
// KMSLibrary is a per-server configuration that will be further augmented with managed key configuration to
// build up a KMS wrapper type to delegate encryption operations to HSMs
type KMSLibrary struct {
UnusedKeys configutil.UnusedKeyMap `hcl:",unusedKeyPositions"`
FoundKeys []string `hcl:",decodedFields"`
Type string `hcl:"-"`
Name string `hcl:"name"`
Library string `hcl:"library"`
}
func (k *KMSLibrary) Validate(source string) []configutil.ConfigError {
return configutil.ValidateUnusedFields(k.UnusedKeys, source)
}
func (k *KMSLibrary) GoString() string {
return fmt.Sprintf("*%#v", *k)
}
func NewConfig() *Config {
return &Config{
SharedConfig: new(configutil.SharedConfig),
@ -569,16 +541,7 @@ func ParseConfig(d, source string) (*Config, error) {
}
}
// Parse KMSLibraries sections if any
if o := list.Filter("kms_library"); len(o.Items) > 0 {
delete(result.UnusedKeys, "kms_library")
if err := parseKmsLibraries(result, o); err != nil {
return nil, fmt.Errorf("error parsing 'kms_library': %w", err)
}
}
entConfig := &(result.entConfig)
if err := entConfig.parseConfig(list); err != nil {
if err := result.parseConfig(list); err != nil {
return nil, fmt.Errorf("error parsing enterprise config: %w", err)
}
@ -843,75 +806,6 @@ func parseServiceRegistration(result *Config, list *ast.ObjectList, name string)
return nil
}
func parseKmsLibraries(result *Config, list *ast.ObjectList) error {
result.KmsLibraries = make(map[string]*KMSLibrary, len(list.Items))
for _, item := range list.Items {
library, err := decodeKmsLibrary(item)
if err != nil {
return err
}
if err := validateKmsLibrary(library); err != nil {
return err
}
if _, ok := result.KmsLibraries[library.Name]; ok {
return fmt.Errorf("duplicated kms_library configuration sections with name %s", library.Name)
}
result.KmsLibraries[library.Name] = library
}
return nil
}
func decodeKmsLibrary(item *ast.ObjectItem) (*KMSLibrary, error) {
library := &KMSLibrary{}
if err := hcl.DecodeObject(&library, item.Val); err != nil {
return nil, multierror.Prefix(err, "kms_library")
}
if len(item.Keys) != 1 {
return nil, errors.New("kms_library section was missing a type")
}
library.Type = strings.ToLower(item.Keys[0].Token.Value().(string))
library.Name = strings.ToLower(library.Name)
return library, nil
}
func defaultKmsLibraryValidator(kms *KMSLibrary) error {
switch kms.Type {
case wrapping.PKCS11:
return fmt.Errorf("KMS type 'pkcs11' requires the Vault Enterprise HSM binary")
default:
return fmt.Errorf("unknown KMS type %q", kms.Type)
}
}
func validateKmsLibrary(kmsConfig *KMSLibrary) error {
if kmsConfig.Library == "" {
return fmt.Errorf("library key can not be blank within kms_library type: %s", kmsConfig.Type)
}
if kmsConfig.Name == "" {
return fmt.Errorf("name key can not be blank within kms_library type: %s", kmsConfig.Type)
}
nameRegex := regexp.MustCompile("^[\\w._-]+$")
if !nameRegex.MatchString(kmsConfig.Name) {
return fmt.Errorf("value ('%s') for name field contained invalid characters within kms_library type: %s", kmsConfig.Name, kmsConfig.Type)
}
if err := kmsLibraryValidator(kmsConfig); err != nil {
return err
}
return nil
}
// Sanitized returns a copy of the config with all values that are considered
// sensitive stripped. It also strips all `*Raw` values that are mainly
// used for parsing.

View File

@ -17,7 +17,3 @@ func TestLoadConfigFile_json2(t *testing.T) {
func TestParseEntropy(t *testing.T) {
testParseEntropy(t, true)
}
func TestKmsLibraryFailsForNonHSMBinary(t *testing.T) {
testKmsLibraryFailsForNonHSMBinary(t)
}

View File

@ -701,7 +701,7 @@ func testConfig_Sanitized(t *testing.T) {
"enable_ui": true,
"enable_response_header_hostname": false,
"enable_response_header_raft_node_id": false,
"log_requests_level": "basic",
"log_requests_level": "basic",
"ha_storage": map[string]interface{}{
"cluster_addr": "top_level_cluster_addr",
"disable_clustering": true,
@ -1064,26 +1064,3 @@ func testConfigRaftAutopilot(t *testing.T) {
t.Fatal(diff)
}
}
func testKmsLibraryFailsForNonHSMBinary(t *testing.T) {
config := `
ui = false
storage "file" {
path = "/tmp/test"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/tls.crt"
tls_key_file = "/opt/vault/tls/tls.key"
}
kms_library "pkcs11" {
name="Logical1"
library="a library"
}
`
_, err := ParseConfig(config, "")
require.Error(t, err)
require.Contains(t, err.Error(), "requires the Vault Enterprise HSM binary")
}