Skip to content
This repository has been archived by the owner on Nov 21, 2023. It is now read-only.

Toggle envoy spiffe auth validator #7

Draft
wants to merge 4 commits into
base: 1-1-4
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ ifeq ($(arch1),x86_64)
arch2=amd64
else ifeq ($(arch1),aarch64)
arch2=arm64
else ifeq ($(arch1),arm64)
arch2=arm64
else
$(error unsupported ARCH: $(arch1))
endif
Expand Down
15 changes: 9 additions & 6 deletions cmd/spire-agent/cli/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ type agentConfig struct {
}

type sdsConfig struct {
DefaultSVIDName string `hcl:"default_svid_name"`
DefaultBundleName string `hcl:"default_bundle_name"`
DefaultAllBundlesName string `hcl:"default_all_bundles_name"`
DefaultSVIDName string `hcl:"default_svid_name"`
DefaultBundleName string `hcl:"default_bundle_name"`
DefaultAllBundlesName string `hcl:"default_all_bundles_name"`
DisableCustomValidation bool `hcl:"disable_custom_validation"`
}

type experimentalConfig struct {
Expand Down Expand Up @@ -409,6 +410,7 @@ func NewAgentConfig(c *Config, logOptions []log.Option, allowUnknownConfig bool)
if ac.DefaultAllBundlesName == ac.DefaultBundleName {
logger.Warn(`The "default_bundle_name" and "default_all_bundles_name" configurables have the same value. "default_all_bundles_name" will be ignored. Please configure distinct values or use the defaults. This will be a configuration error in a future release.`)
}
ac.DisableCustomValidation = c.Agent.SDS.DisableCustomValidation

err = setupTrustBundle(ac, c)
if err != nil {
Expand Down Expand Up @@ -556,9 +558,10 @@ func defaultConfig() *Config {
LogFormat: log.DefaultFormat,
SocketPath: common.DefaultSocketPath,
SDS: sdsConfig{
DefaultBundleName: defaultDefaultBundleName,
DefaultSVIDName: defaultDefaultSVIDName,
DefaultAllBundlesName: defaultDefaultAllBundlesName,
DefaultBundleName: defaultDefaultBundleName,
DefaultSVIDName: defaultDefaultSVIDName,
DefaultAllBundlesName: defaultDefaultAllBundlesName,
DisableCustomValidation: false,
},
},
}
Expand Down
20 changes: 20 additions & 0 deletions cmd/spire-agent/cli/run/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,26 @@ func TestMergeInput(t *testing.T) {
require.Equal(t, "foo", c.Agent.SDS.DefaultAllBundlesName)
},
},
{
msg: "disable_custom_validation should default value of false",
fileInput: func(c *Config) {},
cliInput: func(ac *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.Equal(t, false, c.Agent.SDS.DisableCustomValidation)
},
},
{
msg: "disable_custom_validation should be configurable by file",
fileInput: func(c *Config) {
c.Agent.SDS = sdsConfig{
DisableCustomValidation: true,
}
},
cliInput: func(ac *agentConfig) {},
test: func(t *testing.T, c *Config) {
require.Equal(t, true, c.Agent.SDS.DisableCustomValidation)
},
},
{
msg: "insecure_bootstrap should be configurable by file",
fileInput: func(c *Config) {
Expand Down
3 changes: 3 additions & 0 deletions conf/agent/agent_full.conf
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ agent {
# # all bundles (including federated bundles) with Envoy SDS. Cannot be used with
# # Envoy releases prior to 1.18.
# # default_all_bundles_name = "ALL"

# # disable_custom_validation: disable Envoy SDS custom SPIFFE validation. Default: false
# # disable_custom_validation = false
# }

# allowed_foreign_jwt_claims: set a list of trusted claims to be returned when validating foreign JWTSVIDs
Expand Down
11 changes: 6 additions & 5 deletions doc/spire_agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ Only one of these three options may be set at a time.

### SDS Configuration

| Configuration | Description | Default |
| -------------------------- | ------------------------------------------------------------------------------------------------ | ----------------- |
| `default_svid_name` | The TLS Certificate resource name to use for the default X509-SVID with Envoy SDS | default |
| `default_bundle_name` | The Validation Context resource name to use for the default X.509 bundle with Envoy SDS | ROOTCA |
| `default_all_bundles_name` | The Validation Context resource name to use for all bundles (including federated) with Envoy SDS | ALL |
| Configuration | Description | Default |
| --------------------------- | ------------------------------------------------------------------------------------------------ | ----------------- |
| `default_svid_name` | The TLS Certificate resource name to use for the default X509-SVID with Envoy SDS | default |
| `default_bundle_name` | The Validation Context resource name to use for the default X.509 bundle with Envoy SDS | ROOTCA |
| `default_all_bundles_name` | The Validation Context resource name to use for all bundles (including federated) with Envoy SDS | ALL |
| `disable_custom_validation` | Disable Envoy SDS custom validation | false |

### Profiling Names
These are the available profiles that can be set in the `profiling_freq` configuration value:
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (a *Agent) newEndpoints(metrics telemetry.Metrics, mgr manager.Manager, att
DefaultSVIDName: a.c.DefaultSVIDName,
DefaultBundleName: a.c.DefaultBundleName,
DefaultAllBundlesName: a.c.DefaultAllBundlesName,
DisableCustomValidation: a.c.DisableCustomValidation,
AllowUnauthenticatedVerifiers: a.c.AllowUnauthenticatedVerifiers,
AllowedForeignJWTClaims: a.c.AllowedForeignJWTClaims,
TrustDomain: a.c.TrustDomain,
Expand Down
3 changes: 3 additions & 0 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type Config struct {
// The Validation Context resource name to use for the default X.509 bundle with Envoy SDS
DefaultBundleName string

// Disable custom Envoy SDS validator
DisableCustomValidation bool

// The TLS Certificate resource name to use for the default X509-SVID with Envoy SDS
DefaultSVIDName string

Expand Down
3 changes: 3 additions & 0 deletions pkg/agent/endpoints/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type Config struct {
// The Validation Context resource name to use for the default X.509 bundle with Envoy SDS
DefaultBundleName string

// Disable custom Envoy SDS validator
DisableCustomValidation bool

AllowUnauthenticatedVerifiers bool

AllowedForeignJWTClaims []string
Expand Down
11 changes: 6 additions & 5 deletions pkg/agent/endpoints/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ func New(c Config) *Endpoints {
})

sdsv3Server := c.newSDSv3Server(sdsv3.Config{
Attestor: attestor,
Manager: c.Manager,
DefaultSVIDName: c.DefaultSVIDName,
DefaultBundleName: c.DefaultBundleName,
DefaultAllBundlesName: c.DefaultAllBundlesName,
Attestor: attestor,
Manager: c.Manager,
DefaultSVIDName: c.DefaultSVIDName,
DefaultBundleName: c.DefaultBundleName,
DefaultAllBundlesName: c.DefaultAllBundlesName,
DisableCustomValidation: c.DisableCustomValidation,
})

healthServer := c.newHealthServer(healthv1.Config{
Expand Down
2 changes: 2 additions & 0 deletions pkg/agent/endpoints/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func TestEndpoints(t *testing.T) {
DefaultSVIDName: "DefaultSVIDName",
DefaultBundleName: "DefaultBundleName",
DefaultAllBundlesName: "DefaultAllBundlesName",
DisableCustomValidation: true,
AllowedForeignJWTClaims: tt.allowedClaims,

// Assert the provided config and return a fake Workload API server
Expand Down Expand Up @@ -206,6 +207,7 @@ func TestEndpoints(t *testing.T) {
assert.Equal(t, "DefaultSVIDName", c.DefaultSVIDName)
assert.Equal(t, "DefaultBundleName", c.DefaultBundleName)
assert.Equal(t, "DefaultAllBundlesName", c.DefaultAllBundlesName)
assert.Equal(t, true, c.DisableCustomValidation)
return FakeSDSv3Server{Attestor: attestor}
},

Expand Down
13 changes: 7 additions & 6 deletions pkg/agent/endpoints/sdsv3/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ type Manager interface {
}

type Config struct {
Attestor Attestor
Manager Manager
DefaultAllBundlesName string
DefaultBundleName string
DefaultSVIDName string
Attestor Attestor
Manager Manager
DefaultAllBundlesName string
DefaultBundleName string
DefaultSVIDName string
DisableCustomValidation bool
}

type Handler struct {
Expand Down Expand Up @@ -250,7 +251,7 @@ func (h *Handler) buildResponse(versionInfo string, req *discovery_v3.DiscoveryR

// Use RootCA as default, but replace with SPIFFE auth when Envoy version is at least v1.18.0
var builder validationContextBuilder
if supportsSPIFFEAuthExtension(req) {
if !h.c.DisableCustomValidation && supportsSPIFFEAuthExtension(req) {
builder, err = newSpiffeBuilder(upd.Bundle, upd.FederatedBundles)
if err != nil {
return nil, err
Expand Down
139 changes: 129 additions & 10 deletions pkg/agent/endpoints/sdsv3/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
secret_v3 "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3"
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
"github.com/imdario/mergo"
"github.com/sirupsen/logrus/hooks/test"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/spire/pkg/agent/manager/cache"
Expand Down Expand Up @@ -96,6 +97,19 @@ var (
},
}

tdValidationContext3 = &tls_v3.Secret{
Name: "ALL",
Type: &tls_v3.Secret_ValidationContext{
ValidationContext: &tls_v3.CertificateValidationContext{
TrustedCa: &core_v3.DataSource{
Specifier: &core_v3.DataSource_InlineBytes{
InlineBytes: []byte("-----BEGIN CERTIFICATE-----\nQlVORExF\n-----END CERTIFICATE-----\n"),
},
},
},
},
}

fedBundle = bundleutil.BundleFromRootCA(spiffeid.RequireTrustDomainFromString("otherdomain.test"), &x509.Certificate{
Raw: []byte("FEDBUNDLE"),
})
Expand Down Expand Up @@ -255,6 +269,7 @@ func TestStreamSecrets(t *testing.T) {
for _, tt := range []struct {
name string
req *discovery_v3.DiscoveryRequest
config Config
expectSecrets []*tls_v3.Secret
expectCode codes.Code
expectMsg string
Expand Down Expand Up @@ -407,9 +422,57 @@ func TestStreamSecrets(t *testing.T) {
expectCode: codes.InvalidArgument,
expectMsg: "unable to retrieve all requested identities, missing map[spiffe://domain.test/WHATEVER:true]",
},
{
name: "Disable custom validation",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"default"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ROOTCA",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{workloadTLSCertificate3},
},
{
name: "Disable custom validation and set default bundle name to ALL",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"default"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ALL",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{workloadTLSCertificate3},
},
{
name: "Disable custom validation and set default bundle name to ALL",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"ALL"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ALL",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{tdValidationContext3},
},
} {
t.Run(tt.name, func(t *testing.T) {
test := setupTest(t)
test := setupTestWithConfig(t, tt.config)
defer test.cleanup()

stream, err := test.handler.StreamSecrets(context.Background())
Expand Down Expand Up @@ -627,6 +690,7 @@ func TestFetchSecrets(t *testing.T) {
for _, tt := range []struct {
name string
req *discovery_v3.DiscoveryRequest
config Config
expectSecrets []*tls_v3.Secret
expectCode codes.Code
expectMsg string
Expand Down Expand Up @@ -741,9 +805,57 @@ func TestFetchSecrets(t *testing.T) {
expectCode: codes.InvalidArgument,
expectMsg: `unable to retrieve all requested identities, missing map[spiffe://domain.test/other:true]`,
},
{
name: "Disable custom validation",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"default"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ROOTCA",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{workloadTLSCertificate3},
},
{
name: "Disable custom validation and set default bundle name to ALL",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"default"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ALL",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{workloadTLSCertificate3},
},
{
name: "Disable custom validation and set default bundle name to ALL",
req: &discovery_v3.DiscoveryRequest{
ResourceNames: []string{"ALL"},
Node: &core_v3.Node{
UserAgentVersionType: userAgentVersionTypeV18,
},
},
config: Config{
DefaultSVIDName: "default",
DefaultBundleName: "ALL",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: true,
},
expectSecrets: []*tls_v3.Secret{tdValidationContext3},
},
} {
t.Run(tt.name, func(t *testing.T) {
test := setupTest(t)
test := setupTestWithConfig(t, tt.config)
defer test.server.Stop()

resp, err := test.handler.FetchSecrets(context.Background(), tt.req)
Expand Down Expand Up @@ -773,15 +885,18 @@ func DeltaSecretsTest(t *testing.T) {
require.Nil(t, resp)
}

func setupTest(t *testing.T) *handlerTest {
func setupTestWithConfig(t *testing.T, c Config) *handlerTest {
manager := NewFakeManager(t)
handler := New(Config{
Attestor: FakeAttestor(workloadSelectors),
Manager: manager,
DefaultSVIDName: "default",
DefaultBundleName: "ROOTCA",
DefaultAllBundlesName: "ALL",
})
defaultConfig := Config{
Manager: manager,
Attestor: FakeAttestor(workloadSelectors),
DefaultSVIDName: "default",
DefaultBundleName: "ROOTCA",
DefaultAllBundlesName: "ALL",
DisableCustomValidation: false,
}
require.NoError(t, mergo.Merge(&c, defaultConfig))
handler := New(c)

received := make(chan struct{})
handler.hooks.received = received
Expand Down Expand Up @@ -813,6 +928,10 @@ func setupTest(t *testing.T) *handlerTest {
return test
}

func setupTest(t *testing.T) *handlerTest {
return setupTestWithConfig(t, Config{})
}

type handlerTest struct {
t *testing.T

Expand Down
2 changes: 1 addition & 1 deletion pkg/common/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const (
// IMPORTANT: When updating, make sure to reconcile the versions list that
// is part of the upgrade integration test. See
// test/integration/suites/upgrade/README.md for details.
Base = "1.1.3"
Base = "1.1.5"
)

var (
Expand Down
Loading