Skip to content

Commit

Permalink
Add support for go-sockaddr templated addresses in config. (#9109)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncabatoff committed Oct 21, 2021
1 parent e8e1344 commit 4ef0d3e
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 2 deletions.
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
37 changes: 37 additions & 0 deletions command/server/config_test_helpers.go
Expand Up @@ -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) {
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 @@ -122,6 +123,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 @@ -381,3 +392,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 @@ -47,14 +47,18 @@ default value in the `"/sys/config/ui"` [API endpoint](/api/system/config-ui).
## `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

0 comments on commit 4ef0d3e

Please sign in to comment.