diff --git a/changelog/18227.txt b/changelog/18227.txt new file mode 100644 index 000000000000..477915982d03 --- /dev/null +++ b/changelog/18227.txt @@ -0,0 +1,3 @@ +```release-note:feature +**Server UDS Listener**: Adding listener to Vault server to serve http request via unix domain socket +``` \ No newline at end of file diff --git a/command/server/listener.go b/command/server/listener.go index 4d36a41ebba0..78acbd3e7b92 100644 --- a/command/server/listener.go +++ b/command/server/listener.go @@ -20,7 +20,8 @@ type ListenerFactory func(*configutil.Listener, io.Writer, cli.Ui) (net.Listener // BuiltinListeners is the list of built-in listener types. var BuiltinListeners = map[string]ListenerFactory{ - "tcp": tcpListenerFactory, + "tcp": tcpListenerFactory, + "unix": unixListenerFactory, } // NewListener creates a new listener of the given type with the given diff --git a/command/server/listener_test.go b/command/server/listener_test.go index e36ced7e7603..b1bf62ddfedf 100644 --- a/command/server/listener_test.go +++ b/command/server/listener_test.go @@ -26,6 +26,9 @@ func testListenerImpl(t *testing.T, ln net.Listener, connFn testListenerConnFn, tlsConn.Handshake() } serverCh <- server + if expectedAddr == "" { + return + } addr, _, err := net.SplitHostPort(server.RemoteAddr().String()) if err != nil { t.Error(err) diff --git a/command/server/listener_unix.go b/command/server/listener_unix.go new file mode 100644 index 000000000000..3740b58f7c67 --- /dev/null +++ b/command/server/listener_unix.go @@ -0,0 +1,36 @@ +package server + +import ( + "io" + "net" + + "github.com/hashicorp/go-secure-stdlib/reloadutil" + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/hashicorp/vault/internalshared/listenerutil" + "github.com/mitchellh/cli" +) + +func unixListenerFactory(l *configutil.Listener, _ io.Writer, ui cli.Ui) (net.Listener, map[string]string, reloadutil.ReloadFunc, error) { + addr := l.Address + if addr == "" { + addr = "/run/vault.sock" + } + + var cfg *listenerutil.UnixSocketsConfig + if l.SocketMode != "" && + l.SocketUser != "" && + l.SocketGroup != "" { + cfg = &listenerutil.UnixSocketsConfig{ + Mode: l.SocketMode, + User: l.SocketUser, + Group: l.SocketGroup, + } + } + + ln, err := listenerutil.UnixSocketListener(addr, cfg) + if err != nil { + return nil, nil, nil, err + } + + return ln, map[string]string{}, nil, nil +} diff --git a/command/server/listener_unix_test.go b/command/server/listener_unix_test.go new file mode 100644 index 000000000000..e5254a294795 --- /dev/null +++ b/command/server/listener_unix_test.go @@ -0,0 +1,25 @@ +package server + +import ( + "net" + "path/filepath" + "testing" + + "github.com/hashicorp/vault/internalshared/configutil" + "github.com/mitchellh/cli" +) + +func TestUnixListener(t *testing.T) { + ln, _, _, err := unixListenerFactory(&configutil.Listener{ + Address: filepath.Join(t.TempDir(), "/vault.sock"), + }, nil, cli.NewMockUi()) + if err != nil { + t.Fatalf("err: %s", err) + } + + connFn := func(lnReal net.Listener) (net.Conn, error) { + return net.Dial("unix", ln.Addr().String()) + } + + testListenerImpl(t, ln, connFn, "", 0, "", false) +} diff --git a/website/content/docs/configuration/listener/index.mdx b/website/content/docs/configuration/listener/index.mdx index af45f0e23f32..d088982030f4 100644 --- a/website/content/docs/configuration/listener/index.mdx +++ b/website/content/docs/configuration/listener/index.mdx @@ -9,6 +9,9 @@ description: |- # `listener` Stanza The `listener` stanza configures the addresses and ports on which Vault will -respond to requests. At this time, there is only one listener - [TCP][tcp]. +respond to requests. At this time, there are two listeners: +- [TCP][tcp] +- [Unix Domain Socket][unix] [tcp]: /docs/configuration/listener/tcp +[unix]: /docs/configuration/listener/unix diff --git a/website/content/docs/configuration/listener/unix.mdx b/website/content/docs/configuration/listener/unix.mdx new file mode 100644 index 000000000000..e338edb268b6 --- /dev/null +++ b/website/content/docs/configuration/listener/unix.mdx @@ -0,0 +1,69 @@ +--- +layout: docs +page_title: Unix - Listeners - Configuration +description: |- + The Unix listener configures Vault to listen on the specified Unix domain socket. +--- + +# `unix` Listener + +The Unix listener configures Vault to listen on the specified Unix domain socket. + +```hcl +listener "unix" { + address = "/run/vault.sock" +} +``` + +The `listener` stanza may be specified more than once to make Vault listen on +multiple sockets. + +## `unix` Listener Parameters +- `address` `(string: "/run/vault.sock", )` – Specifies the address to bind the Unix socket. + +- `socket_mode` `(string: "", )` – Changes the access + permissions and the special mode flags of the Unix socket. + +- `socket_user` `(string: "", )` – Changes the user owner of the Unix socket. + +- `socket_group` `(string: "", )` – Changes the group owner of the Unix socket. + + +## `unix` Listener Examples + +### Listening on Multiple Sockets + +This example shows Vault listening on a specified socket, as well as the default. + +```hcl +listener "unix" {} + +listener "unix" { + address = "/var/run/vault.sock" +} +``` + +### Listening on Multiple Interfaces + +This example shows Vault listening on TCP localhost, as well as Unix socket. + +```hcl +listener "unix" { + address = "/var/run/vault.sock" +} + +listener "tcp" { + address = "127.0.0.1:8200" +} +``` + +### Configuring Permissions +This example shows changing access permissions and ownership of the Unix socket. +```hcl +listener "unix" { + address = "/var/run/vault.sock" + socket_mode = "644" + socket_user = "1000" + socket_group = "1000" +} +``` \ No newline at end of file diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 391082398feb..71e063d02cfb 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -214,6 +214,10 @@ { "title": "TCP", "path": "configuration/listener/tcp" + }, + { + "title": "Unix", + "path": "configuration/listener/unix" } ] },