Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 7 commits into from Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/9109.txt
@@ -0,0 +1,3 @@
```release-note:improvement
core: Add support for go-sockaddr templated addresses in config.
```
11 changes: 11 additions & 0 deletions command/server/config.go
Expand Up @@ -392,6 +392,17 @@ func ParseConfig(d, source string) (*Config, error) {
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)
if err != nil {
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions command/server/config_test.go
Expand Up @@ -36,6 +36,10 @@ func TestParseListeners(t *testing.T) {
testParseListeners(t)
}

func TestParseSockaddrTemplate(t *testing.T) {
testParseSockaddrTemplate(t)
}

func TestConfigRaftRetryJoin(t *testing.T) {
testConfigRaftRetryJoin(t)
}
Expand Down
39 changes: 38 additions & 1 deletion command/server/config_test_helpers.go
Expand Up @@ -486,7 +486,7 @@ func testUnknownFieldValidation(t *testing.T) {
for _, er1 := range errors {
found := false
if strings.Contains(er1.String(), "sentinel") {
//This happens on OSS, and is fine
// This happens on OSS, and is fine
continue
}
for _, ex := range expected {
Expand Down Expand Up @@ -828,6 +828,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) {
config, err := LoadConfigFile("./test-fixtures/config_seals.hcl")
if err != nil {
Expand Down
30 changes: 30 additions & 0 deletions internalshared/configutil/listener.go
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/go-secure-stdlib/tlsutil"
"github.com/hashicorp/go-sockaddr"
"github.com/hashicorp/go-sockaddr/template"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
)
Expand Down Expand Up @@ -118,6 +119,16 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error {
if err := hcl.DecodeObject(&l, item.Val); err != nil {
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
var m map[string]interface{}
Expand Down Expand Up @@ -366,3 +377,22 @@ func ParseListeners(result *SharedConfig, list *ast.ObjectList) error {

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)
}
}
8 changes: 6 additions & 2 deletions website/content/docs/configuration/listener/tcp.mdx
Expand Up @@ -24,14 +24,18 @@ advertise the correct address to other nodes.
## `tcp` Listener Parameters

- `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
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
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
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
wait for the next request when keep-alives are enabled. If `http_idle_timeout`
Expand Down