Skip to content

Commit

Permalink
[Unprivileged] Adjust the control socket path add --path.socket opt…
Browse files Browse the repository at this point in the history
…ion (#3909)
  • Loading branch information
blakerouse authored Jan 5, 2024
1 parent bc3bbfd commit 602a2b4
Show file tree
Hide file tree
Showing 30 changed files with 269 additions and 266 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: feature

# Change summary; a 80ish characters long description of the change.
summary: Move control socket path to the installation directory

# Long description; in case the summary is not enough to describe the change
# this field accommodate a description without length limits.
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
#description:

# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
component:

# PR URL; optional; the PR number that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
pr: https://github.com/elastic/elastic-agent/pull/3909

# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
issue: https://github.com/elastic/elastic-agent/issues/3840
7 changes: 4 additions & 3 deletions internal/pkg/agent/application/info/agent_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ package info
import (
"context"
"fmt"

"runtime"
"strings"

"github.com/elastic/elastic-agent/pkg/core/logger"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
"github.com/elastic/elastic-agent/internal/pkg/agent/errors"
"github.com/elastic/elastic-agent/internal/pkg/release"
"github.com/elastic/elastic-agent/pkg/core/logger"
"github.com/elastic/elastic-agent/pkg/features"

"github.com/elastic/go-sysinfo"
Expand Down Expand Up @@ -168,7 +169,7 @@ func (i *AgentInfo) ECSMetadata(l *logger.Logger) (*ECSMeta, error) {
BuildOriginal: release.Info().String(),
// only upgradeable if running from Agent installer and running under the
// control of the system supervisor (or built specifically with upgrading enabled)
Upgradeable: release.Upgradeable() || (RunningInstalled() && RunningUnderSupervisor()),
Upgradeable: release.Upgradeable() || (paths.RunningInstalled() && RunningUnderSupervisor()),
LogLevel: i.LogLevel(),
},
},
Expand Down
38 changes: 0 additions & 38 deletions internal/pkg/agent/application/info/state.go

This file was deleted.

22 changes: 0 additions & 22 deletions internal/pkg/agent/application/info/state_unix.go

This file was deleted.

81 changes: 70 additions & 11 deletions internal/pkg/agent/application/paths/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,30 @@ import (
"sync"

"github.com/elastic/elastic-agent/internal/pkg/release"
"github.com/elastic/elastic-agent/pkg/utils"
)

const (
// DefaultConfigName is the default name of the configuration file.
DefaultConfigName = "elastic-agent.yml"

// AgentLockFileName is the name of the overall Elastic Agent file lock.
AgentLockFileName = "agent.lock"
tempSubdir = "tmp"
tempSubdirPerms = 0o770

// ControlSocketName is the control socket name.
ControlSocketName = "elastic-agent.sock"

// WindowsControlSocketInstalledPath is the control socket path used when installed on Windows.
WindowsControlSocketInstalledPath = `npipe:///elastic-agent-system`

// MarkerFileName is the name of the file that's created by
// `elastic-agent install` in the Agent's topPath folder to
// indicate that the Agent executing from the binary under
// the same topPath folder is an installed Agent.
MarkerFileName = ".installed"

tempSubdir = "tmp"
tempSubdirPerms = 0o770

darwin = "darwin"
)
Expand All @@ -31,21 +46,23 @@ const (
var ExternalInputsPattern = filepath.Join("inputs.d", "*.yml")

var (
topPath string
configPath string
configFilePath string
logsPath string
downloadsPath string
componentsPath string
installPath string
unversionedHome bool
tmpCreator sync.Once
topPath string
configPath string
configFilePath string
logsPath string
downloadsPath string
componentsPath string
installPath string
controlSocketPath string
unversionedHome bool
tmpCreator sync.Once
)

func init() {
topPath = initialTop()
configPath = topPath
logsPath = topPath
controlSocketPath = initialControlSocketPath(topPath)
unversionedHome = false // only versioned by container subcommand

// these should never change
Expand All @@ -61,6 +78,7 @@ func init() {
fs.StringVar(&configFilePath, "c", DefaultConfigName, "Configuration file, relative to path.config")
fs.StringVar(&logsPath, "path.logs", logsPath, "Logs path contains Agent log output")
fs.StringVar(&installPath, "path.install", installPath, "DEPRECATED, setting this flag has no effect since v8.6.0")
fs.StringVar(&controlSocketPath, "path.socket", controlSocketPath, "Control protocol socket path for the Agent")

// enable user to download update artifacts to alternative place
// TODO: remove path.downloads support on next major (this can be configured using `agent.download.targetDirectory`)
Expand Down Expand Up @@ -199,6 +217,18 @@ func SetInstall(path string) {
installPath = path
}

// ControlSocket returns the control socket directory for Agent
func ControlSocket() string {
return controlSocketPath
}

// SetControlSocket overrides the ControlSocket path.
//
// Used by the container subcommand to adjust the control socket path.
func SetControlSocket(path string) {
controlSocketPath = path
}

// initialTop returns the initial top-level path for the binary
//
// When nested in top-level/data/elastic-agent-${hash}/ the result is top-level/.
Expand Down Expand Up @@ -267,3 +297,32 @@ func InstallPath(basePath string) string {
func TopBinaryPath() string {
return filepath.Join(Top(), BinaryName)
}

// RunningInstalled returns true when executing Agent is the installed Agent.
func RunningInstalled() bool {
// Check if install marker created by `elastic-agent install` exists
markerFilePath := filepath.Join(Top(), MarkerFileName)
if _, err := os.Stat(markerFilePath); err != nil {
return false
}
return true
}

// ControlSocketFromPath returns the control socket path for an Elastic Agent running
// on the defined platform, and its executing directory.
func ControlSocketFromPath(platform string, path string) string {
// socket should be inside this directory
socketPath := filepath.Join(path, ControlSocketName)
if platform == "windows" {
// on windows the control socket always uses the fallback
return utils.SocketURLWithFallback(socketPath, path)
}
unixSocket := fmt.Sprintf("unix://%s", socketPath)
if len(unixSocket) < 104 {
// small enough to fit
return unixSocket
}
// place in global /tmp to ensure that its small enough to fit; current path is way to long
// for it to be used, but needs to be unique per Agent (in the case that multiple are running)
return utils.SocketURLWithFallback(socketPath, path)
}
12 changes: 0 additions & 12 deletions internal/pkg/agent/application/paths/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@ const (
// for installing Elastic Agent's files.
DefaultBasePath = "/opt"

// ControlSocketPath is the control socket path used when installed.
ControlSocketPath = "unix:///run/elastic-agent.sock"

// ControlSocketUnprivilegedPath is the control socket path used when installed as non-root.
// This must exist inside of a directory in '/run/' because the permissions need to be set
// on that directory during installation time, because once the service is spawned it will not
// have permissions to create the socket in the '/run/' directory.
ControlSocketUnprivilegedPath = "unix:///run/elastic-agent/elastic-agent.sock"

// ShipperSocketPipePattern is the socket path used when installed for a shipper pipe.
ShipperSocketPipePattern = "unix:///run/elastic-agent-%s-pipe.sock"

// ServiceName is the service name when installed.
ServiceName = "elastic-agent"

Expand Down
14 changes: 3 additions & 11 deletions internal/pkg/agent/application/paths/paths_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,9 @@ const (
// for installing Elastic Agent's files.
DefaultBasePath = "/Library"

// ControlSocketPath is the control socket path used when installed.
ControlSocketPath = "unix:///var/run/elastic-agent.sock"

// ControlSocketUnprivilegedPath is the control socket path used when installed as non-root.
// This must exist inside of a directory in '/var/run/' because the permissions need to be set
// on that directory during installation time, because once the service is spawned it will not
// have permissions to create the socket in the '/var/run/' directory.
ControlSocketUnprivilegedPath = "unix:///var/run/elastic-agent/elastic-agent.sock"

// ShipperSocketPipePattern is the socket path used when installed for a shipper pipe.
ShipperSocketPipePattern = "unix:///var/run/elastic-agent-%s-pipe.sock"
// ControlSocketRunSymlink is the path to the symlink that should be
// created to the control socket when Elastic Agent is running with root.
ControlSocketRunSymlink = "/var/run/elastic-agent.sock"

// ServiceName is the service name when installed.
ServiceName = "co.elastic.elastic-agent"
Expand Down
10 changes: 8 additions & 2 deletions internal/pkg/agent/application/paths/paths_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ package paths

import "path/filepath"

// defaultAgentVaultPath is the directory for linux where the vault store is located or the
const defaultAgentVaultPath = "vault"
const (
// ControlSocketRunSymlink is the path to the symlink that should be
// created to the control socket when Elastic Agent is running with root.
ControlSocketRunSymlink = "/run/elastic-agent.sock"

// defaultAgentVaultPath is the directory for linux where the vault store is located or the
defaultAgentVaultPath = "vault"
)

// AgentVaultPath is the directory that contains all the files for the value
func AgentVaultPath() string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

//go:build windows
//go:build !windows

package info
package paths

import (
"github.com/elastic/elastic-agent/pkg/utils"
"runtime"
)

func fixInstallMarkerPermissions(markerFilePath string, ownership utils.FileOwner) error {
// TODO(blakerouse): Fix the market permissions on Windows.
return nil
func initialControlSocketPath(topPath string) string {
return ControlSocketFromPath(runtime.GOOS, topPath)
}

// ResolveControlSocket does nothing on non-Windows hosts.
func ResolveControlSocket() {}
33 changes: 25 additions & 8 deletions internal/pkg/agent/application/paths/paths_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package paths

import (
"path/filepath"
"runtime"
"strings"
)

Expand All @@ -19,14 +20,8 @@ const (
// for installing Elastic Agent's files.
DefaultBasePath = `C:\Program Files`

// ControlSocketPath is the control socket path used when installed.
ControlSocketPath = `\\.\pipe\elastic-agent-system`

// ControlSocketUnprivilegedPath is the control socket path used when installed as non-root.
ControlSocketUnprivilegedPath = ControlSocketPath

// ShipperSocketPipePattern is the socket path used when installed for a shipper pipe.
ShipperSocketPipePattern = `\\.\pipe\elastic-agent-%s-pipe.sock`
// ControlSocketRunSymlink is not created on Windows.
ControlSocketRunSymlink = ""

// ServiceName is the service name when installed.
ServiceName = "Elastic Agent"
Expand All @@ -50,3 +45,25 @@ func ArePathsEqual(expected, actual string) bool {
func AgentVaultPath() string {
return filepath.Join(Config(), defaultAgentVaultPath)
}

func initialControlSocketPath(topPath string) string {
// when installed the control address is fixed
if RunningInstalled() {
return WindowsControlSocketInstalledPath
}
return ControlSocketFromPath(runtime.GOOS, topPath)
}

// ResolveControlSocket updates the control socket path.
//
// Called during the upgrade process from pre-8.8 versions. In pre-8.8 versions the
// RunningInstalled will always be false, even when it is an installed version. Once
// that is fixed from the upgrade process the control socket path needs to be updated.
func ResolveControlSocket() {
currentPath := ControlSocket()
if currentPath == ControlSocketFromPath(runtime.GOOS, topPath) && RunningInstalled() {
// path is not correct being that it's installed
// reset the control socket path to be the installed path
SetControlSocket(WindowsControlSocketInstalledPath)
}
}
2 changes: 1 addition & 1 deletion internal/pkg/agent/application/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type Upgrader struct {
func IsUpgradeable() bool {
// only upgradeable if running from Agent installer and running under the
// control of the system supervisor (or built specifically with upgrading enabled)
return release.Upgradeable() || (info.RunningInstalled() && info.RunningUnderSupervisor())
return release.Upgradeable() || (paths.RunningInstalled() && info.RunningUnderSupervisor())
}

// NewUpgrader creates an upgrader which is capable of performing upgrade operation
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/agent/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command {
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.logs"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.downloads"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.install"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.socket"))

// logging flags
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("v"))
Expand Down
Loading

0 comments on commit 602a2b4

Please sign in to comment.