Skip to content

Commit

Permalink
Add TempDir option to UnixSocketConfig (#282)
Browse files Browse the repository at this point in the history
* Add TempDir option to UnixSocketConfig. Allows clients to specify
  a folder where plugin-specific Unix socket directories should be
  created. Still defaults to $TMPDIR (if set) or /tmp.
* Improve UnixSocketConfig field names and comments
* Document exported Unix socket environment variables
  • Loading branch information
tomhjp committed Sep 21, 2023
1 parent 2caaccb commit 2f6e0c5
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
33 changes: 16 additions & 17 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,15 @@ type UnixSocketConfig struct {
// client process must be a member of this group or chown will fail.
Group string

// The directory to create Unix sockets in. Internally managed by go-plugin
// and deleted when the plugin is killed.
directory string
}

func unixSocketConfigFromEnv() UnixSocketConfig {
return UnixSocketConfig{
Group: os.Getenv(EnvUnixSocketGroup),
directory: os.Getenv(EnvUnixSocketDir),
}
// TempDir specifies the base directory to use when creating a plugin-specific
// temporary directory. It is expected to already exist and be writable. If
// not set, defaults to the directory chosen by os.MkdirTemp.
TempDir string

// The directory to create Unix sockets in. Internally created and managed
// by go-plugin and deleted when the plugin is killed. Will be created
// inside TempDir if specified.
socketDir string
}

// ReattachConfig is used to configure a client to reattach to an
Expand Down Expand Up @@ -467,7 +466,7 @@ func (c *Client) Kill() {
c.l.Lock()
runner := c.runner
addr := c.address
hostSocketDir := c.unixSocketCfg.directory
hostSocketDir := c.unixSocketCfg.socketDir
c.l.Unlock()

// If there is no runner or ID, there is nothing to kill.
Expand Down Expand Up @@ -652,7 +651,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
}

if c.config.UnixSocketConfig != nil {
c.unixSocketCfg.Group = c.config.UnixSocketConfig.Group
c.unixSocketCfg = *c.config.UnixSocketConfig
}

if c.unixSocketCfg.Group != "" {
Expand All @@ -662,22 +661,22 @@ func (c *Client) Start() (addr net.Addr, err error) {
var runner runner.Runner
switch {
case c.config.RunnerFunc != nil:
c.unixSocketCfg.directory, err = os.MkdirTemp("", "plugin-dir")
c.unixSocketCfg.socketDir, err = os.MkdirTemp(c.unixSocketCfg.TempDir, "plugin-dir")
if err != nil {
return nil, err
}
// os.MkdirTemp creates folders with 0o700, so if we have a group
// configured we need to make it group-writable.
if c.unixSocketCfg.Group != "" {
err = setGroupWritable(c.unixSocketCfg.directory, c.unixSocketCfg.Group, 0o770)
err = setGroupWritable(c.unixSocketCfg.socketDir, c.unixSocketCfg.Group, 0o770)
if err != nil {
return nil, err
}
}
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvUnixSocketDir, c.unixSocketCfg.directory))
c.logger.Trace("created temporary directory for unix sockets", "dir", c.unixSocketCfg.directory)
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvUnixSocketDir, c.unixSocketCfg.socketDir))
c.logger.Trace("created temporary directory for unix sockets", "dir", c.unixSocketCfg.socketDir)

runner, err = c.config.RunnerFunc(c.logger, cmd, c.unixSocketCfg.directory)
runner, err = c.config.RunnerFunc(c.logger, cmd, c.unixSocketCfg.socketDir)
if err != nil {
return nil, err
}
Expand Down
12 changes: 11 additions & 1 deletion client_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"syscall"
"testing"
Expand All @@ -29,6 +30,11 @@ func TestSetGroup(t *testing.T) {
if err != nil {
t.Fatal(err)
}
baseTempDir := t.TempDir()
baseTempDir, err = filepath.EvalSymlinks(baseTempDir)
if err != nil {
t.Fatal(err)
}
for name, tc := range map[string]struct {
group string
}{
Expand All @@ -41,14 +47,18 @@ func TestSetGroup(t *testing.T) {
HandshakeConfig: testHandshake,
Plugins: testPluginMap,
UnixSocketConfig: &UnixSocketConfig{
Group: tc.group,
Group: tc.group,
TempDir: baseTempDir,
},
RunnerFunc: func(l hclog.Logger, cmd *exec.Cmd, tmpDir string) (runner.Runner, error) {
// Run tests inside the RunnerFunc to ensure we don't race
// with the code that deletes tmpDir when the client fails
// to start properly.

// Test that it creates a directory with the proper owners and permissions.
if filepath.Dir(tmpDir) != baseTempDir {
t.Errorf("Expected base TempDir to be %s, but tmpDir was %s", baseTempDir, tmpDir)
}
info, err := os.Lstat(tmpDir)
if err != nil {
t.Fatal(err)
Expand Down
7 changes: 6 additions & 1 deletion constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
package plugin

const (
EnvUnixSocketDir = "PLUGIN_UNIX_SOCKET_DIR"
// EnvUnixSocketDir specifies the directory that _plugins_ should create unix
// sockets in. Does not affect client behavior.
EnvUnixSocketDir = "PLUGIN_UNIX_SOCKET_DIR"

// EnvUnixSocketGroup specifies the owning, writable group to set for Unix
// sockets created by _plugins_. Does not affect client behavior.
EnvUnixSocketGroup = "PLUGIN_UNIX_SOCKET_GROUP"
)
9 changes: 8 additions & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ type ServeTestConfig struct {
SyncStdio bool
}

func unixSocketConfigFromEnv() UnixSocketConfig {
return UnixSocketConfig{
Group: os.Getenv(EnvUnixSocketGroup),
socketDir: os.Getenv(EnvUnixSocketDir),
}
}

// protocolVersion determines the protocol version and plugin set to be used by
// the server. In the event that there is no suitable version, the last version
// in the config is returned leaving the client to report the incompatibility.
Expand Down Expand Up @@ -547,7 +554,7 @@ func serverListener_tcp() (net.Listener, error) {
}

func serverListener_unix(unixSocketCfg UnixSocketConfig) (net.Listener, error) {
tf, err := os.CreateTemp(unixSocketCfg.directory, "plugin")
tf, err := os.CreateTemp(unixSocketCfg.socketDir, "plugin")
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 2f6e0c5

Please sign in to comment.