Add support for go-sockaddr templated addresses in config. (#9109)

This commit is contained in:
Nick Cabatoff 2021-10-21 10:10:48 -04:00 committed by GitHub
parent 1898e6c301
commit d66fd98d4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 2 deletions

3
changelog/9109.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
core: Add support for go-sockaddr templated addresses in config.
```

View File

@ -392,6 +392,17 @@ func ParseConfig(d, source string) (*Config, error) {
return nil, err return nil, err
} }
if rendered, err := configutil.ParseSingleIPTemplate(result.APIAddr); err != nil {
return nil, err
} else {
result.APIAddr = rendered
}
if rendered, err := configutil.ParseSingleIPTemplate(result.ClusterAddr); err != nil {
return nil, err
} else {
result.ClusterAddr = rendered
}
sharedConfig, err := configutil.ParseConfig(d) sharedConfig, err := configutil.ParseConfig(d)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -36,6 +36,10 @@ func TestParseListeners(t *testing.T) {
testParseListeners(t) testParseListeners(t)
} }
func TestParseSockaddrTemplate(t *testing.T) {
testParseSockaddrTemplate(t)
}
func TestConfigRaftRetryJoin(t *testing.T) { func TestConfigRaftRetryJoin(t *testing.T) {
testConfigRaftRetryJoin(t) testConfigRaftRetryJoin(t)
} }

View File

@ -843,6 +843,43 @@ listener "tcp" {
} }
} }
func testParseSockaddrTemplate(t *testing.T) {
config, err := ParseConfig(`
api_addr = <<EOF
{{- GetAllInterfaces | include "flags" "loopback" | include "type" "ipv4" | attr "address" -}}
EOF
listener "tcp" {
address = <<EOF
{{- GetAllInterfaces | include "flags" "loopback" | include "type" "ipv4" | attr "address" -}}:443
EOF
cluster_address = <<EOF
{{- GetAllInterfaces | include "flags" "loopback" | include "type" "ipv4" | attr "address" -}}:8201
EOF
tls_disable = true
}`, "")
if err != nil {
t.Fatal(err)
}
expected := &Config{
APIAddr: "127.0.0.1",
SharedConfig: &configutil.SharedConfig{
Listeners: []*configutil.Listener{
{
Type: "tcp",
Address: "127.0.0.1:443",
ClusterAddress: "127.0.0.1:8201",
TLSDisable: true,
},
},
},
}
config.Prune()
if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
func testParseSeals(t *testing.T) { func testParseSeals(t *testing.T) {
config, err := LoadConfigFile("./test-fixtures/config_seals.hcl") config, err := LoadConfigFile("./test-fixtures/config_seals.hcl")
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/go-secure-stdlib/tlsutil" "github.com/hashicorp/go-secure-stdlib/tlsutil"
"github.com/hashicorp/go-sockaddr" "github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/go-sockaddr/template"
"github.com/hashicorp/hcl" "github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast" "github.com/hashicorp/hcl/hcl/ast"
) )
@ -122,6 +123,16 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error {
if err := hcl.DecodeObject(&l, item.Val); err != nil { if err := hcl.DecodeObject(&l, item.Val); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i)) return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
} }
if rendered, err := ParseSingleIPTemplate(l.Address); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
} else {
l.Address = rendered
}
if rendered, err := ParseSingleIPTemplate(l.ClusterAddress); err != nil {
return multierror.Prefix(err, fmt.Sprintf("listeners.%d:", i))
} else {
l.ClusterAddress = rendered
}
// Hacky way, for now, to get the values we want for sanitizing // Hacky way, for now, to get the values we want for sanitizing
var m map[string]interface{} var m map[string]interface{}
@ -381,3 +392,22 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error {
return nil return nil
} }
// ParseSingleIPTemplate is used as a helper function to parse out a single IP
// address from a config parameter.
func ParseSingleIPTemplate(ipTmpl string) (string, error) {
out, err := template.Parse(ipTmpl)
if err != nil {
return "", fmt.Errorf("unable to parse address template %q: %v", ipTmpl, err)
}
ips := strings.Split(out, " ")
switch len(ips) {
case 0:
return "", errors.New("no addresses found, please configure one")
case 1:
return strings.TrimSpace(ips[0]), nil
default:
return "", fmt.Errorf("multiple addresses found (%q), please configure one", out)
}
}

View File

@ -47,14 +47,18 @@ default value in the `"/sys/config/ui"` [API endpoint](/api/system/config-ui).
## `tcp` Listener Parameters ## `tcp` Listener Parameters
- `address` `(string: "127.0.0.1:8200")` Specifies the address to bind to for - `address` `(string: "127.0.0.1:8200")` Specifies the address to bind to for
listening. listening. This can be dynamically defined with a
[go-sockaddr template](https://pkg.go.dev/github.com/hashicorp/go-sockaddr/template)
that is resolved at runtime.
- `cluster_address` `(string: "127.0.0.1:8201")` Specifies the address to bind - `cluster_address` `(string: "127.0.0.1:8201")` Specifies the address to bind
to for cluster server-to-server requests. This defaults to one port higher to for cluster server-to-server requests. This defaults to one port higher
than the value of `address`. This does not usually need to be set, but can be than the value of `address`. This does not usually need to be set, but can be
useful in case Vault servers are isolated from each other in such a way that useful in case Vault servers are isolated from each other in such a way that
they need to hop through a TCP load balancer or some other scheme in order to they need to hop through a TCP load balancer or some other scheme in order to
talk. talk. This can be dynamically defined with a
[go-sockaddr template](https://pkg.go.dev/github.com/hashicorp/go-sockaddr/template)
that is resolved at runtime.
- `http_idle_timeout` `(string: "5m")` - Specifies the maximum amount of time to - `http_idle_timeout` `(string: "5m")` - Specifies the maximum amount of time to
wait for the next request when keep-alives are enabled. If `http_idle_timeout` wait for the next request when keep-alives are enabled. If `http_idle_timeout`