diff --git a/core/capabilities/confidentialrelay/handler.go b/core/capabilities/confidentialrelay/handler.go index 8a60d8388d7..1f99867b58c 100644 --- a/core/capabilities/confidentialrelay/handler.go +++ b/core/capabilities/confidentialrelay/handler.go @@ -112,10 +112,14 @@ type Handler struct { // validateAttestation validates TEE attestation documents. // Defaults to the Nitro validator; overridden in tests. validateAttestation attestationValidatorFunc - limitsFactory limits.Factory + // trustEnclaves relaxes attestation validation for fake (non-Nitro) + // enclaves. INSECURE; test-only. When set, the custom-CA-roots validation + // path is skipped in favour of validateAttestation (the accept-all func). + trustEnclaves bool + limitsFactory limits.Factory } -func NewHandler(capRegistry core.CapabilitiesRegistry, conn core.GatewayConnector, responseSigner relayResponseSigner, lggr logger.Logger, lf limits.Factory) (*Handler, error) { +func NewHandler(capRegistry core.CapabilitiesRegistry, conn core.GatewayConnector, responseSigner relayResponseSigner, lggr logger.Logger, lf limits.Factory, trustEnclaves bool) (*Handler, error) { if responseSigner == nil { return nil, errors.New("response signer is required") } @@ -124,13 +128,20 @@ func NewHandler(capRegistry core.CapabilitiesRegistry, conn core.GatewayConnecto return nil, fmt.Errorf("failed to create metrics: %w", err) } + named := logger.Named(lggr, HandlerName) + validate := nitro.ValidateAttestation + if trustEnclaves { + validate = func(_, _, _ []byte) error { return nil } + } + h := &Handler{ capRegistry: capRegistry, gatewayConnector: conn, responseSigner: responseSigner, - lggr: logger.Named(lggr, HandlerName), + lggr: named, metrics: m, - validateAttestation: nitro.ValidateAttestation, + validateAttestation: validate, + trustEnclaves: trustEnclaves, limitsFactory: lf, } h.Service, h.eng = services.Config{ @@ -622,7 +633,7 @@ func (h *Handler) verifyAttestationHash(ctx context.Context, attestationB64 stri var validationErr error for _, m := range measurements { var err error - if caRootsPEM != "" { + if caRootsPEM != "" && !h.trustEnclaves { err = nitro.ValidateAttestationWithRoots(attestationBytes, hash, m, caRootsPEM) } else { err = h.validateAttestation(attestationBytes, hash, m) diff --git a/core/capabilities/confidentialrelay/handler_test.go b/core/capabilities/confidentialrelay/handler_test.go index 2967c395bd3..4ee7bb4c587 100644 --- a/core/capabilities/confidentialrelay/handler_test.go +++ b/core/capabilities/confidentialrelay/handler_test.go @@ -132,7 +132,7 @@ func newTestHandler(t *testing.T, registry core.CapabilitiesRegistry, gwConn cor require.NoError(t, err) key, err := p2pkey.NewV2() require.NoError(t, err) - h, err := NewHandler(registry, gwConn, newRelayResponseSigner(key), lggr, limits.Factory{Logger: lggr}) + h, err := NewHandler(registry, gwConn, newRelayResponseSigner(key), lggr, limits.Factory{Logger: lggr}, false) require.NoError(t, err) h.validateAttestation = noopValidator return h diff --git a/core/capabilities/confidentialrelay/service.go b/core/capabilities/confidentialrelay/service.go index 9be91349698..dd6ba1ffce4 100644 --- a/core/capabilities/confidentialrelay/service.go +++ b/core/capabilities/confidentialrelay/service.go @@ -31,6 +31,7 @@ type Service struct { peerID p2pkey.PeerID lggr logger.Logger limitsFactory limits.Factory + trustEnclaves bool handler *Handler } @@ -42,6 +43,7 @@ func NewService( peerID p2pkey.PeerID, lggr logger.Logger, limitsFactory limits.Factory, + trustEnclaves bool, ) *Service { s := &Service{ wrapper: wrapper, @@ -50,6 +52,7 @@ func NewService( peerID: peerID, lggr: lggr, limitsFactory: limitsFactory, + trustEnclaves: trustEnclaves, } s.Service, s.eng = services.Config{ Name: "ConfidentialRelayService", @@ -68,7 +71,7 @@ func (s *Service) start(ctx context.Context) error { if err != nil { return fmt.Errorf("failed to get p2p key for confidential relay signing: %w", err) } - h, err := NewHandler(s.capRegistry, conn, newRelayResponseSigner(key), s.lggr, s.limitsFactory) + h, err := NewHandler(s.capRegistry, conn, newRelayResponseSigner(key), s.lggr, s.limitsFactory, s.trustEnclaves) if err != nil { return err } diff --git a/core/config/cre_config.go b/core/config/cre_config.go index 15a77f4a86e..2781ef75064 100644 --- a/core/config/cre_config.go +++ b/core/config/cre_config.go @@ -25,6 +25,9 @@ type WorkflowFetcher interface { // CREConfidentialRelay defines configuration for the confidential relay handler. type CREConfidentialRelay interface { Enabled() bool + // TrustEnclaves reports whether the relay should trust fake (non-Nitro) + // enclaves by relaxing TEE attestation validation. INSECURE; test-only. + TrustEnclaves() bool } // CRELinking defines configuration for connecting to the CRE linking service diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index f37e63fd41a..e680cd20e16 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -969,6 +969,8 @@ DebugMode = false # Default [CRE.ConfidentialRelay] # Enabled controls whether the confidential relay gateway handler should be configured. Enabled = false # Default +# TrustEnclaves relaxes TEE attestation validation so the relay trusts fake (non-Nitro) enclaves. intended only for tests. +TrustEnclaves = false # Default # Sharding holds settings for node sharding configuration. [Sharding] diff --git a/core/config/toml/types.go b/core/config/toml/types.go index adc5c681064..63ff0f4abc1 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1957,6 +1957,10 @@ type WorkflowFetcherConfig struct { // validating enclave attestations and proxying capability requests. type ConfidentialRelayConfig struct { Enabled *bool `toml:",omitempty"` + // TrustEnclaves relaxes TEE attestation validation so the relay trusts + // fake (non-Nitro) enclaves. INSECURE; intended only for tests/E2E that run + // against the fake enclave environment. + TrustEnclaves *bool `toml:",omitempty"` } // LinkingConfig holds the configuration for connecting to the CRE linking service @@ -2020,6 +2024,9 @@ func (c *CreConfig) setFrom(f *CreConfig) { if v := f.ConfidentialRelay.Enabled; v != nil { c.ConfidentialRelay.Enabled = v } + if v := f.ConfidentialRelay.TrustEnclaves; v != nil { + c.ConfidentialRelay.TrustEnclaves = v + } } } diff --git a/core/services/chainlink/config_cre.go b/core/services/chainlink/config_cre.go index ff58345c9a6..775e2b39fc6 100644 --- a/core/services/chainlink/config_cre.go +++ b/core/services/chainlink/config_cre.go @@ -106,10 +106,12 @@ func (c *creConfig) Linking() config.CRELinking { } type confidentialRelayConfig struct { - enabled bool + enabled bool + trustEnclaves bool } -func (cr *confidentialRelayConfig) Enabled() bool { return cr.enabled } +func (cr *confidentialRelayConfig) Enabled() bool { return cr.enabled } +func (cr *confidentialRelayConfig) TrustEnclaves() bool { return cr.trustEnclaves } func (c *creConfig) ConfidentialRelay() config.CREConfidentialRelay { if c.c.ConfidentialRelay == nil { @@ -119,7 +121,11 @@ func (c *creConfig) ConfidentialRelay() config.CREConfidentialRelay { if c.c.ConfidentialRelay.Enabled != nil { enabled = *c.c.ConfidentialRelay.Enabled } - return &confidentialRelayConfig{enabled: enabled} + trustEnclaves := false + if c.c.ConfidentialRelay.TrustEnclaves != nil { + trustEnclaves = *c.c.ConfidentialRelay.TrustEnclaves + } + return &confidentialRelayConfig{enabled: enabled, trustEnclaves: trustEnclaves} } func (c *creConfig) LocalSecretOverrides() map[string]map[string]string { diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 127261bc388..4b81abff647 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -593,7 +593,8 @@ func TestConfig_Marshal(t *testing.T) { TLSEnabled: ptr(true), }, ConfidentialRelay: &toml.ConfidentialRelayConfig{ - Enabled: ptr(false), + Enabled: new(bool), + TrustEnclaves: new(bool), }, } full.Billing = toml.Billing{ diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index f6eb5121505..c95082005a2 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -386,6 +386,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 782db0949d7..4b8a44cbed5 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -425,6 +425,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 86121aaa1b8..a47d93fa3ce 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -386,6 +386,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/core/services/cre/cre.go b/core/services/cre/cre.go index bf3d74cc9cb..f92f8cddd3d 100644 --- a/core/services/cre/cre.go +++ b/core/services/cre/cre.go @@ -217,6 +217,7 @@ func (s *Services) newSubservices( confidentialRelayPeerID(cfg, capCfg), lggr, opts.LimitsFactory, + cfg.CRE().ConfidentialRelay().TrustEnclaves(), ) srvs = append(srvs, relayService) } diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index f6eb5121505..c95082005a2 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -386,6 +386,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index dd7fb035052..f82eb098335 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -404,6 +404,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 68a0130ae84..edd22d0da41 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -386,6 +386,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/docs/CONFIG.md b/docs/CONFIG.md index d283f2faf4a..d8273ce7c05 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2724,6 +2724,7 @@ DebugMode enables additional tracing and logging for workflow engines. ```toml [CRE.ConfidentialRelay] Enabled = false # Default +TrustEnclaves = false # Default ``` @@ -2733,6 +2734,12 @@ Enabled = false # Default ``` Enabled controls whether the confidential relay gateway handler should be configured. +### TrustEnclaves +```toml +TrustEnclaves = false # Default +``` +TrustEnclaves relaxes TEE attestation validation so the relay trusts fake (non-Nitro) enclaves. intended only for tests. + ## Sharding ```toml [Sharding] diff --git a/system-tests/lib/cre/features/confidentialrelay/confidentialrelay.go b/system-tests/lib/cre/features/confidentialrelay/confidentialrelay.go index f6f72802ac3..17f54164f79 100644 --- a/system-tests/lib/cre/features/confidentialrelay/confidentialrelay.go +++ b/system-tests/lib/cre/features/confidentialrelay/confidentialrelay.go @@ -17,7 +17,11 @@ import ( const flag = cre.ConfidentialRelayCapability -type ConfidentialRelay struct{} +type ConfidentialRelay struct { + // TrustEnclaves makes the relay trust fake (non-Nitro) enclaves by + // relaxing TEE attestation validation. INSECURE; test/E2E use only. + TrustEnclaves bool +} func (o *ConfidentialRelay) Flag() cre.CapabilityFlag { return flag @@ -59,7 +63,11 @@ func (o *ConfidentialRelay) PreEnvStartup( } enabled := true - typedConfig.CRE.ConfidentialRelay = &coretoml.ConfidentialRelayConfig{Enabled: &enabled} + trustEnclaves := o.TrustEnclaves + typedConfig.CRE.ConfidentialRelay = &coretoml.ConfidentialRelayConfig{ + Enabled: &enabled, + TrustEnclaves: &trustEnclaves, + } out, err := tomlser.Marshal(typedConfig) if err != nil { diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index 06ac519d21d..105b7e61686 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -533,6 +533,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 87476ac18f8..2bbb80ee01a 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -398,6 +398,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index a0bd0f22ca8..48f058be61e 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -459,6 +459,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index b514320e81e..67f4aa4fd36 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -442,6 +442,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 09d630f0410..ea414ddad3f 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -442,6 +442,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index efa55d6c4a3..ed9379e7659 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -442,6 +442,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar index 4f5406cf44d..24c918961cf 100644 --- a/testdata/scripts/node/validate/fallback-override.txtar +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -544,6 +544,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 63ac3270c61..c6bd8e6bfb5 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -427,6 +427,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 2ea583aa574..012b0a8ce20 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -438,6 +438,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = '' diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index d8a68cdc8a4..8f43ed3c2cf 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -439,6 +439,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319' diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index cc7c437f38a..6c9c3ea134f 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -421,6 +421,7 @@ TLSEnabled = true [CRE.ConfidentialRelay] Enabled = false +TrustEnclaves = false [Billing] URL = 'localhost:4319'