mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-03 20:40:45 -05:00
* add test for issue * add bool to disable json limit parsing * clean up tests * fix godoc * restore previous clustering setup * add nil check for VaultNodeConfig * add changelog * move docker test to appropriate directory to allow testing in CI --------- Co-authored-by: davidadeleon <56207066+davidadeleon@users.noreply.github.com> Co-authored-by: davidadeleon <ddeleon@hashicorp.com>
This commit is contained in:
parent
b03ed9cf7f
commit
6c2f2a84ee
7 changed files with 63 additions and 19 deletions
3
changelog/_10848.txt
Normal file
3
changelog/_10848.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
http: skip JSON limit parsing on cluster listener
|
||||||
|
```
|
||||||
|
|
@ -1514,8 +1514,10 @@ func (c *ServerCommand) Run(args []string) int {
|
||||||
// mode if it's set
|
// mode if it's set
|
||||||
core.SetClusterListenerAddrs(clusterAddrs)
|
core.SetClusterListenerAddrs(clusterAddrs)
|
||||||
core.SetClusterHandler(vaulthttp.Handler.Handler(&vault.HandlerProperties{
|
core.SetClusterHandler(vaulthttp.Handler.Handler(&vault.HandlerProperties{
|
||||||
Core: core,
|
Core: core,
|
||||||
ListenerConfig: &configutil.Listener{},
|
ListenerConfig: &configutil.Listener{
|
||||||
|
DisableJSONLimitParsing: true,
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Attempt unsealing in a background goroutine. This is needed for when a
|
// Attempt unsealing in a background goroutine. This is needed for when a
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ func wrapJSONLimitsHandler(handler http.Handler, props *vault.HandlerProperties)
|
||||||
var maxRequestSize, maxJSONDepth, maxStringValueLength, maxObjectEntryCount, maxArrayElementCount, maxToken int64
|
var maxRequestSize, maxJSONDepth, maxStringValueLength, maxObjectEntryCount, maxArrayElementCount, maxToken int64
|
||||||
|
|
||||||
if props.ListenerConfig != nil {
|
if props.ListenerConfig != nil {
|
||||||
|
// Check to see if limits are disabled
|
||||||
|
if props.ListenerConfig.DisableJSONLimitParsing {
|
||||||
|
handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
maxRequestSize = props.ListenerConfig.MaxRequestSize
|
maxRequestSize = props.ListenerConfig.MaxRequestSize
|
||||||
maxJSONDepth = props.ListenerConfig.CustomMaxJSONDepth
|
maxJSONDepth = props.ListenerConfig.CustomMaxJSONDepth
|
||||||
maxStringValueLength = props.ListenerConfig.CustomMaxJSONStringValueLength
|
maxStringValueLength = props.ListenerConfig.CustomMaxJSONStringValueLength
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,11 @@ type Listener struct {
|
||||||
|
|
||||||
// JSON-specific limits
|
// JSON-specific limits
|
||||||
|
|
||||||
|
// DisableJSONLimitParsing disables the checking for JSON limits. This is only applicable to
|
||||||
|
// the listener config passed into the Cluster listener since this would impact forwarded
|
||||||
|
// requests that have already been checked via the API listener on the originating node.
|
||||||
|
DisableJSONLimitParsing bool `hcl:"-"`
|
||||||
|
|
||||||
// CustomMaxJSONDepth specifies the maximum nesting depth of a JSON object.
|
// CustomMaxJSONDepth specifies the maximum nesting depth of a JSON object.
|
||||||
CustomMaxJSONDepthRaw interface{} `hcl:"max_json_depth"`
|
CustomMaxJSONDepthRaw interface{} `hcl:"max_json_depth"`
|
||||||
CustomMaxJSONDepth int64 `hcl:"-"`
|
CustomMaxJSONDepth int64 `hcl:"-"`
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"maps"
|
||||||
"math/big"
|
"math/big"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -669,6 +670,11 @@ func (n *DockerClusterNode) Start(ctx context.Context, opts *DockerClusterOption
|
||||||
defaultListenerConfig = n.createDefaultListenerConfig()
|
defaultListenerConfig = n.createDefaultListenerConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge custom listener config options to default config
|
||||||
|
if opts.VaultNodeConfig != nil && opts.VaultNodeConfig.CustomListenerConfigOpts != nil {
|
||||||
|
maps.Copy(defaultListenerConfig["tcp"].(map[string]interface{}), opts.VaultNodeConfig.CustomListenerConfigOpts)
|
||||||
|
}
|
||||||
|
|
||||||
listenerConfig = append(listenerConfig, defaultListenerConfig)
|
listenerConfig = append(listenerConfig, defaultListenerConfig)
|
||||||
ports := []string{"8200/tcp", "8201/tcp"}
|
ports := []string{"8200/tcp", "8201/tcp"}
|
||||||
|
|
||||||
|
|
@ -1424,6 +1430,28 @@ func (dc *DockerCluster) GetActiveClusterNode() *DockerClusterNode {
|
||||||
return dc.ClusterNodes[node]
|
return dc.ClusterNodes[node]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dc *DockerCluster) GetActiveAndStandbys() (*DockerClusterNode, []*DockerClusterNode) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
activeIndex, err := testcluster.WaitForActiveNode(ctx, dc)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("no cluster node became active in timeout window: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
var leaderNode *DockerClusterNode
|
||||||
|
var standbyNodes []*DockerClusterNode
|
||||||
|
for i, node := range dc.ClusterNodes {
|
||||||
|
if i == activeIndex {
|
||||||
|
leaderNode = node
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
standbyNodes = append(standbyNodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaderNode, standbyNodes
|
||||||
|
}
|
||||||
|
|
||||||
/* Notes on testing the non-bridge network case:
|
/* Notes on testing the non-bridge network case:
|
||||||
- you need the test itself to be running in a container so that it can use
|
- you need the test itself to be running in a container so that it can use
|
||||||
the network; create the network using
|
the network; create the network using
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,10 @@ type VaultNodeConfig struct {
|
||||||
// ServiceRegistrationType string
|
// ServiceRegistrationType string
|
||||||
// ServiceRegistrationOptions map[string]string
|
// ServiceRegistrationOptions map[string]string
|
||||||
|
|
||||||
StorageOptions map[string]string `json:"-"`
|
StorageOptions map[string]string `json:"-"`
|
||||||
AdditionalListeners []VaultNodeListenerConfig `json:"-"`
|
AdditionalListeners []VaultNodeListenerConfig `json:"-"`
|
||||||
AdditionalTCPPorts []int `json:"-"`
|
CustomListenerConfigOpts map[string]interface{} `json:"-"`
|
||||||
|
AdditionalTCPPorts []int `json:"-"`
|
||||||
|
|
||||||
DefaultMaxRequestDuration time.Duration `json:"default_max_request_duration"`
|
DefaultMaxRequestDuration time.Duration `json:"default_max_request_duration"`
|
||||||
LogFormat string `json:"log_format"`
|
LogFormat string `json:"log_format"`
|
||||||
|
|
|
||||||
|
|
@ -1096,6 +1096,7 @@ type TestClusterOptions struct {
|
||||||
SkipInit bool
|
SkipInit bool
|
||||||
HandlerFunc HandlerHandler
|
HandlerFunc HandlerHandler
|
||||||
DefaultHandlerProperties HandlerProperties
|
DefaultHandlerProperties HandlerProperties
|
||||||
|
ClusterHandlerProperties HandlerProperties
|
||||||
|
|
||||||
// BaseListenAddress is used to explicitly assign ports in sequence to the
|
// BaseListenAddress is used to explicitly assign ports in sequence to the
|
||||||
// listener of each core. It should be a string of the form
|
// listener of each core. It should be a string of the form
|
||||||
|
|
@ -1210,7 +1211,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
}
|
}
|
||||||
|
|
||||||
var numCores int
|
var numCores int
|
||||||
if opts == nil || opts.NumCores == 0 {
|
if opts.NumCores == 0 {
|
||||||
numCores = DefaultNumCores
|
numCores = DefaultNumCores
|
||||||
} else {
|
} else {
|
||||||
numCores = opts.NumCores
|
numCores = opts.NumCores
|
||||||
|
|
@ -1225,13 +1226,13 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
var testCluster TestCluster
|
var testCluster TestCluster
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case opts != nil && opts.Logger != nil && !reflect.ValueOf(opts.Logger).IsNil():
|
case opts.Logger != nil && !reflect.ValueOf(opts.Logger).IsNil():
|
||||||
testCluster.Logger = opts.Logger
|
testCluster.Logger = opts.Logger
|
||||||
default:
|
default:
|
||||||
testCluster.Logger = corehelpers.NewTestLogger(t)
|
testCluster.Logger = corehelpers.NewTestLogger(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts != nil && opts.TempDir != "" {
|
if opts.TempDir != "" {
|
||||||
if _, err := os.Stat(opts.TempDir); os.IsNotExist(err) {
|
if _, err := os.Stat(opts.TempDir); os.IsNotExist(err) {
|
||||||
if err := os.MkdirAll(opts.TempDir, 0o700); err != nil {
|
if err := os.MkdirAll(opts.TempDir, 0o700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -1247,7 +1248,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
}
|
}
|
||||||
|
|
||||||
var caKey *ecdsa.PrivateKey
|
var caKey *ecdsa.PrivateKey
|
||||||
if opts != nil && opts.CAKey != nil {
|
if opts.CAKey != nil {
|
||||||
caKey = opts.CAKey
|
caKey = opts.CAKey
|
||||||
} else {
|
} else {
|
||||||
caKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
caKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
|
@ -1257,7 +1258,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
}
|
}
|
||||||
testCluster.CAKey = caKey
|
testCluster.CAKey = caKey
|
||||||
var caBytes []byte
|
var caBytes []byte
|
||||||
if opts != nil && len(opts.CACert) > 0 {
|
if len(opts.CACert) > 0 {
|
||||||
caBytes = opts.CACert
|
caBytes = opts.CACert
|
||||||
} else {
|
} else {
|
||||||
caCertTemplate := &x509.Certificate{
|
caCertTemplate := &x509.Certificate{
|
||||||
|
|
@ -1418,7 +1419,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
NextProtos: []string{"h2", "http/1.1"},
|
NextProtos: []string{"h2", "http/1.1"},
|
||||||
GetCertificate: certGetter.GetCertificate,
|
GetCertificate: certGetter.GetCertificate,
|
||||||
}
|
}
|
||||||
if opts != nil && opts.RequireClientAuth {
|
if opts.RequireClientAuth {
|
||||||
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||||
testCluster.ClientAuthRequired = true
|
testCluster.ClientAuthRequired = true
|
||||||
}
|
}
|
||||||
|
|
@ -1603,7 +1604,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
testCluster.LicensePrivateKey = priKey
|
testCluster.LicensePrivateKey = priKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts != nil && opts.InmemClusterLayers {
|
if opts.InmemClusterLayers {
|
||||||
if opts.ClusterLayers != nil {
|
if opts.ClusterLayers != nil {
|
||||||
t.Fatalf("cannot specify ClusterLayers when InmemClusterLayers is true")
|
t.Fatalf("cannot specify ClusterLayers when InmemClusterLayers is true")
|
||||||
}
|
}
|
||||||
|
|
@ -1614,7 +1615,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
opts.ClusterLayers = inmemCluster
|
opts.ClusterLayers = inmemCluster
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts != nil && len(opts.Plugins) != 0 {
|
if len(opts.Plugins) != 0 {
|
||||||
var plugins []pluginhelpers.TestPlugin
|
var plugins []pluginhelpers.TestPlugin
|
||||||
for _, pluginType := range opts.Plugins {
|
for _, pluginType := range opts.Plugins {
|
||||||
if pluginType.Container && runtime.GOOS != "linux" {
|
if pluginType.Container && runtime.GOOS != "linux" {
|
||||||
|
|
@ -1694,7 +1695,7 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
testCluster.Cores = ret
|
testCluster.Cores = ret
|
||||||
|
|
||||||
// Initialize cores
|
// Initialize cores
|
||||||
if opts == nil || !opts.SkipInit {
|
if !opts.SkipInit {
|
||||||
testCluster.initCores(t, opts)
|
testCluster.initCores(t, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1716,11 +1717,9 @@ func NewTestCluster(t testing.TB, base *CoreConfig, opts *TestClusterOptions) *T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
if opts != nil {
|
if opts.SetupFunc != nil {
|
||||||
if opts.SetupFunc != nil {
|
testCluster.SetupFunc = func() {
|
||||||
testCluster.SetupFunc = func() {
|
opts.SetupFunc(t, &testCluster)
|
||||||
opts.SetupFunc(t, &testCluster)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue