Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions cmd/spire-agent/cli/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ type agentConfig struct {
ServerAddress string `hcl:"server_address"`
ServerPort int `hcl:"server_port"`
SocketPath string `hcl:"socket_path"`
DisableWorkloadAPI bool `hcl:"disable_workload_api"`
DisableSDSAPI bool `hcl:"disable_sds_api"`
WorkloadX509SVIDKeyType string `hcl:"workload_x509_svid_key_type"`
TrustBundleFormat string `hcl:"trust_bundle_format"`
TrustBundlePath string `hcl:"trust_bundle_path"`
Expand Down Expand Up @@ -483,6 +485,8 @@ func parseFlags(name string, args []string, output io.Writer) (*agentConfig, err
flags.StringVar(&c.ServerAddress, "serverAddress", "", "IP address or DNS name of the SPIRE server")
flags.IntVar(&c.ServerPort, "serverPort", 0, "Port number of the SPIRE server")
flags.StringVar(&c.TrustDomain, "trustDomain", "", "The trust domain that this agent belongs to")
flags.BoolVar(&c.DisableWorkloadAPI, "disableWorkloadAPI", false, "Disable the SPIFFE Workload API")
flags.BoolVar(&c.DisableSDSAPI, "disableSDSAPI", false, "Disable the Envoy SDS API")
flags.StringVar(&c.TrustBundlePath, "trustBundle", "", "Path to the SPIRE server CA bundle")
flags.StringVar(&c.TrustBundleURL, "trustBundleUrl", "", "URL to download the SPIRE server CA bundle")
flags.StringVar(&c.TrustBundleFormat, "trustBundleFormat", "", fmt.Sprintf("Format of the bootstrap trust bundle, %q or %q", trustbundlesources.BundleFormatPEM, trustbundlesources.BundleFormatSPIFFE))
Expand Down Expand Up @@ -524,6 +528,10 @@ func mergeInput(fileInput *Config, cliInput *agentConfig) (*Config, error) {
return c, nil
}

func (c *agentConfig) endpointEnabled() bool {
return !c.DisableWorkloadAPI || !c.DisableSDSAPI
}

func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool) (*agent.Config, error) {
ac := &agent.Config{}

Expand Down Expand Up @@ -632,11 +640,15 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
}
ac.TrustDomain = td

addr, err := c.Agent.getAddr()
if err != nil {
return nil, err
ac.DisableWorkloadAPI = c.Agent.DisableWorkloadAPI
ac.DisableSDSAPI = c.Agent.DisableSDSAPI
if c.Agent.endpointEnabled() {
addr, err := c.Agent.getAddr()
if err != nil {
return nil, err
}
ac.BindAddress = addr
}
ac.BindAddress = addr

if c.Agent.hasAdminAddr() {
adminAddr, err := c.Agent.getAdminAddr()
Expand Down
42 changes: 24 additions & 18 deletions cmd/spire-agent/cli/run/run_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,19 @@ func (c *agentConfig) getAddr() (net.Addr, error) {
}

func (c *agentConfig) getAdminAddr() (net.Addr, error) {
socketPathAbs, err := filepath.Abs(c.SocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for socket_path: %w", err)
}
adminSocketPathAbs, err := filepath.Abs(c.AdminSocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for admin_socket_path: %w", err)
}

if strings.HasPrefix(adminSocketPathAbs, filepath.Dir(socketPathAbs)+"/") {
return nil, errors.New("admin socket cannot be in the same directory or a subdirectory as that containing the Workload API socket")
if c.endpointEnabled() {
socketPathAbs, err := filepath.Abs(c.SocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for socket_path: %w", err)
}
if strings.HasPrefix(adminSocketPathAbs, filepath.Dir(socketPathAbs)+"/") {
return nil, errors.New("admin socket cannot be in the same directory or a subdirectory as that containing the Workload API socket")
}
}

return &net.UnixAddr{
Expand All @@ -56,17 +58,19 @@ func (c *agentConfig) hasAdminAddr() bool {
// brokerSocketAddr resolves the UDS branch of broker bind-address selection.
// Returns the platform-agnostic TCP branch is handled in brokerBindAddr.
func (c *agentConfig) brokerSocketAddr() (net.Addr, error) {
socketPathAbs, err := filepath.Abs(c.SocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for socket_path: %w", err)
}
brokerSocketPathAbs, err := filepath.Abs(c.Experimental.Broker.SocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for experimental.broker.socket_path: %w", err)
}

if strings.HasPrefix(brokerSocketPathAbs, filepath.Dir(socketPathAbs)+"/") {
return nil, errors.New("broker socket cannot be in the same directory or a subdirectory as that containing the Workload API socket")
if c.endpointEnabled() {
socketPathAbs, err := filepath.Abs(c.SocketPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for socket_path: %w", err)
}
if strings.HasPrefix(brokerSocketPathAbs, filepath.Dir(socketPathAbs)+"/") {
return nil, errors.New("broker socket cannot be in the same directory or a subdirectory as that containing the Workload API socket")
}
}

return &net.UnixAddr{
Expand All @@ -87,12 +91,14 @@ func (c *agentConfig) validateOS() error {
}

func prepareEndpoints(c *agent.Config) error {
// Create uds dir and parents if not exists
dir := filepath.Dir(c.BindAddress.String())
if _, statErr := os.Stat(dir); os.IsNotExist(statErr) {
c.Log.WithField("dir", dir).Infof("Creating spire agent UDS directory")
if err := os.MkdirAll(dir, 0755); err != nil {
return err
if c.BindAddress != nil {
// Create uds dir and parents if not exists
dir := filepath.Dir(c.BindAddress.String())
if _, statErr := os.Stat(dir); os.IsNotExist(statErr) {
c.Log.WithField("dir", dir).Infof("Creating spire agent UDS directory")
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
}
}

Expand Down
55 changes: 55 additions & 0 deletions cmd/spire-agent/cli/run/run_posix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func TestParseFlagsGood(t *testing.T) {
"-serverAddress=127.0.0.1",
"-serverPort=8081",
"-socketPath=/tmp/spire-agent/public/api.sock",
"-disableWorkloadAPI",
"-disableSDSAPI",
"-trustBundle=conf/agent/dummy_root_ca.crt",
"-trustBundleUrl=https://test.url",
"-trustDomain=example.org",
Expand All @@ -162,6 +164,8 @@ func TestParseFlagsGood(t *testing.T) {
assert.Equal(t, c.ServerAddress, "127.0.0.1")
assert.Equal(t, c.ServerPort, 8081)
assert.Equal(t, c.SocketPath, "/tmp/spire-agent/public/api.sock")
assert.True(t, c.DisableWorkloadAPI)
assert.True(t, c.DisableSDSAPI)
assert.Equal(t, c.TrustBundlePath, "conf/agent/dummy_root_ca.crt")
assert.Equal(t, c.TrustBundleURL, "https://test.url")
assert.Equal(t, c.TrustDomain, "example.org")
Expand Down Expand Up @@ -296,6 +300,20 @@ func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase {
require.Equal(t, "unix", c.AdminBindAddress.Network())
},
},
{
msg: "admin_socket_path can share disabled public endpoint socket directory",
input: func(c *Config) {
c.Agent.SocketPath = "/tmp/workload.sock"
c.Agent.DisableWorkloadAPI = true
c.Agent.DisableSDSAPI = true
c.Agent.AdminSocketPath = "/tmp/admin.sock"
},
test: func(t *testing.T, c *agent.Config) {
require.Nil(t, c.BindAddress)
require.Equal(t, "/tmp/admin.sock", c.AdminBindAddress.String())
require.Equal(t, "unix", c.AdminBindAddress.Network())
},
},
{
msg: "admin_socket_path configured with similar folder that socket_path",
input: func(c *Config) {
Expand Down Expand Up @@ -331,6 +349,18 @@ func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase {
require.Nil(t, c)
},
},
{
msg: "admin_socket_path same folder as socket_path when only workload API is disabled",
expectError: true,
input: func(c *Config) {
c.Agent.SocketPath = "/tmp/workload.sock"
c.Agent.DisableWorkloadAPI = true
c.Agent.AdminSocketPath = "/tmp/admin.sock"
},
test: func(t *testing.T, c *agent.Config) {
require.Nil(t, c)
},
},
{
msg: "admin_socket_path configured with subfolder socket_path",
expectError: true,
Expand All @@ -353,6 +383,31 @@ func newAgentConfigCasesOS(t *testing.T) []newAgentConfigCase {
require.Nil(t, c)
},
},
{
msg: "broker socket can share disabled public endpoint socket directory",
input: func(c *Config) {
c.Agent.SocketPath = "/tmp/workload.sock"
c.Agent.DisableWorkloadAPI = true
c.Agent.DisableSDSAPI = true
c.Agent.Experimental.Broker = &brokerHCLConfig{
SocketPath: "/tmp/broker.sock",
Brokers: []brokerHCLEntry{
{
ID: "spiffe://example.org/broker",
AllowedReferenceTypes: []brokerAllowedReferenceTypeHCLEntry{
{TypeURL: "type.googleapis.com/spiffe.broker.WorkloadPIDReference"},
},
},
},
}
},
test: func(t *testing.T, c *agent.Config) {
require.Nil(t, c.BindAddress)
require.Len(t, c.Broker.BindAddresses, 1)
require.Equal(t, "/tmp/broker.sock", c.Broker.BindAddresses[0].String())
require.Equal(t, "unix", c.Broker.BindAddresses[0].Network())
},
},
{
msg: "admin_socket_path not provided",
input: func(c *Config) {
Expand Down
99 changes: 99 additions & 0 deletions cmd/spire-agent/cli/run/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,62 @@ func TestMergeInput(t *testing.T) {
require.Equal(t, "bar", c.Agent.TrustDomain)
},
},
{
msg: "disable_workload_api should default to false",
fileInput: func(c *Config) {},
cliInput: func(c *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.False(t, c.Agent.DisableWorkloadAPI)
},
},
{
msg: "disable_workload_api should be configurable by file",
fileInput: func(c *Config) {
c.Agent.DisableWorkloadAPI = true
},
cliInput: func(c *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.True(t, c.Agent.DisableWorkloadAPI)
},
},
{
msg: "disable_workload_api should be configurable by CLI flag",
fileInput: func(c *Config) {},
cliInput: func(c *agentConfig) {
c.DisableWorkloadAPI = true
},
test: func(t *testing.T, c *Config) {
require.True(t, c.Agent.DisableWorkloadAPI)
},
},
{
msg: "disable_sds_api should default to false",
fileInput: func(c *Config) {},
cliInput: func(c *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.False(t, c.Agent.DisableSDSAPI)
},
},
{
msg: "disable_sds_api should be configurable by file",
fileInput: func(c *Config) {
c.Agent.DisableSDSAPI = true
},
cliInput: func(c *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.True(t, c.Agent.DisableSDSAPI)
},
},
{
msg: "disable_sds_api should be configurable by CLI flag",
fileInput: func(c *Config) {},
cliInput: func(c *agentConfig) {
c.DisableSDSAPI = true
},
test: func(t *testing.T, c *Config) {
require.True(t, c.Agent.DisableSDSAPI)
},
},
{
msg: "require_pq_kem should be configurable by file",
fileInput: func(c *Config) {
Expand Down Expand Up @@ -993,6 +1049,49 @@ func TestNewAgentConfig(t *testing.T) {
assert.True(t, c.DisableSPIFFECertValidation)
},
},
{
msg: "public endpoint is enabled by default",
input: func(c *Config) {},
test: func(t *testing.T, c *agent.Config) {
require.NotNil(t, c.BindAddress)
require.False(t, c.DisableWorkloadAPI)
require.False(t, c.DisableSDSAPI)
},
},
{
msg: "disable_workload_api keeps public endpoint enabled",
input: func(c *Config) {
c.Agent.DisableWorkloadAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.NotNil(t, c.BindAddress)
require.True(t, c.DisableWorkloadAPI)
require.False(t, c.DisableSDSAPI)
},
},
{
msg: "disable_sds_api keeps public endpoint enabled",
input: func(c *Config) {
c.Agent.DisableSDSAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.NotNil(t, c.BindAddress)
require.False(t, c.DisableWorkloadAPI)
require.True(t, c.DisableSDSAPI)
},
},
{
msg: "disable_workload_api and disable_sds_api disable public endpoint",
input: func(c *Config) {
c.Agent.DisableWorkloadAPI = true
c.Agent.DisableSDSAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.Nil(t, c.BindAddress)
require.True(t, c.DisableWorkloadAPI)
require.True(t, c.DisableSDSAPI)
},
},
{
msg: "allowed_foreign_jwt_claims no provided",
input: func(c *Config) {
Expand Down
41 changes: 41 additions & 0 deletions cmd/spire-agent/cli/run/run_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ func TestParseFlagsGood(t *testing.T) {
"-serverAddress=127.0.0.1",
"-serverPort=8081",
"-namedPipeName=\\spire-agent\\public\\api",
"-disableWorkloadAPI",
"-disableSDSAPI",
"-trustBundle=conf/agent/dummy_root_ca.crt",
"-trustBundleUrl=https://test.url",
"-trustDomain=example.org",
Expand All @@ -148,6 +150,8 @@ func TestParseFlagsGood(t *testing.T) {
assert.Equal(t, "127.0.0.1", c.ServerAddress)
assert.Equal(t, 8081, c.ServerPort)
assert.Equal(t, "\\spire-agent\\public\\api", c.Experimental.NamedPipeName)
assert.True(t, c.DisableWorkloadAPI)
assert.True(t, c.DisableSDSAPI)
assert.Equal(t, "conf/agent/dummy_root_ca.crt", c.TrustBundlePath)
assert.Equal(t, "https://test.url", c.TrustBundleURL)
assert.Equal(t, "example.org", c.TrustDomain)
Expand Down Expand Up @@ -271,6 +275,43 @@ func newAgentConfigCasesOS(*testing.T) []newAgentConfigCase {
require.Equal(t, "pipe", c.BindAddress.(*namedpipe.Addr).Network())
},
},
{
msg: "disable_workload_api keeps named pipe enabled",
input: func(c *Config) {
c.Agent.Experimental.NamedPipeName = "foo"
c.Agent.DisableWorkloadAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.Equal(t, "\\\\.\\pipe\\foo", c.BindAddress.String())
require.True(t, c.DisableWorkloadAPI)
require.False(t, c.DisableSDSAPI)
},
},
{
msg: "disable_sds_api keeps named pipe enabled",
input: func(c *Config) {
c.Agent.Experimental.NamedPipeName = "foo"
c.Agent.DisableSDSAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.Equal(t, "\\\\.\\pipe\\foo", c.BindAddress.String())
require.False(t, c.DisableWorkloadAPI)
require.True(t, c.DisableSDSAPI)
},
},
{
msg: "disable_workload_api and disable_sds_api disable named pipe",
input: func(c *Config) {
c.Agent.Experimental.NamedPipeName = "foo"
c.Agent.DisableWorkloadAPI = true
c.Agent.DisableSDSAPI = true
},
test: func(t *testing.T, c *agent.Config) {
require.Nil(t, c.BindAddress)
require.True(t, c.DisableWorkloadAPI)
require.True(t, c.DisableSDSAPI)
},
},
{
msg: "admin_named_pipe_name not provided",
input: func(c *Config) {
Expand Down
Loading
Loading