From 816dcf814aff1ab5ca043eb47849162a61bc184b Mon Sep 17 00:00:00 2001 From: Pavel <177363085+pkcll@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:24:12 -0500 Subject: [PATCH] Beholder CSA Authentication (#15160) * Bump chainlink-common to PR latest * Wire up Beholder auth in loop * Move keystore auth into NewApplication * Wire up CSA Auth for Beholder * Use simplified auth header approach * Add auth header after logging config * Remove empty line for linter * Put back mistakenly removed imports * Update to latest chainlink-common@INFOPLAT-1071-beholder-csa-signer-auth_2 * Rename return vars Co-authored-by: Jordan Krage * Bump chainlink-common from latest INFOPLAT-1071-beholder-csa-signer-auth_2 * Bump chainlink-common to latest INFOPLAT-1071-beholder-csa-signer-auth_2 * Bump chainlink-common to latest INFOPLAT-1071-beholder-csa-signer-auth_2 * go mod tidy for ./integration-tests * make gomodtidy * Add changeset file * Potential test fix * Clean up the test: remove a few unused mocks * Revert "Clean up the test: remove a few unused mocks" This reverts commit f55cc8ea9d7c3d275f289c1c41b2fe19d7dbf483. * Revert "Potential test fix" This reverts commit cb348aa73e0ff0a95aa5841e46a3cdd581366dee. * Adding InstanceAppFactoryWithKeystoreMock for shell_local tests (#15167) * Revert "remove go.mod replace with real version (#15142)" This reverts commit d61ce5142f9cfc2e1835f84a04515a4045414a13. * Run go mod tidy * Add Beholder auth to deployment LoopRegistry * Update chainlink-common to PR latest * Run go mod tidy * Prep keystore for beholder auth * Bump chainlink-common to latest * Run go mod tidy --------- Co-authored-by: 4of9 <177086174+4of9@users.noreply.github.com> Co-authored-by: Geert G <117188496+cll-gg@users.noreply.github.com> Co-authored-by: Jordan Krage Co-authored-by: patrickhuie19 Co-authored-by: krehermann <16602512+krehermann@users.noreply.github.com> --- .changeset/swift-fireants-compare.md | 5 +++ core/cmd/key_store_authenticator.go | 4 +- core/cmd/shell.go | 37 ++++++++++++++----- core/cmd/shell_local.go | 11 ++---- core/cmd/shell_local_test.go | 4 +- core/cmd/shell_test.go | 4 +- core/internal/cltest/cltest.go | 4 +- core/internal/cltest/mocks.go | 22 +++++++++-- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/chainlink/application.go | 6 ++- .../relayer_chain_interoperators_test.go | 2 +- core/services/keystore/beholder.go | 19 ++++++++++ .../ccip/testhelpers/integration/chainlink.go | 7 +++- .../testhelpers_1_4_0/chainlink.go | 8 +++- core/web/loop_registry_internal_test.go | 4 +- deployment/environment/memory/node.go | 12 ++++-- deployment/go.mod | 2 +- deployment/go.sum | 4 +- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- plugins/loop_registry.go | 28 +++++++++----- plugins/loop_registry_test.go | 2 +- 27 files changed, 143 insertions(+), 66 deletions(-) create mode 100644 .changeset/swift-fireants-compare.md create mode 100644 core/services/keystore/beholder.go diff --git a/.changeset/swift-fireants-compare.md b/.changeset/swift-fireants-compare.md new file mode 100644 index 00000000000..b11c516e7c3 --- /dev/null +++ b/.changeset/swift-fireants-compare.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add CSA authentication support to Beholder #added diff --git a/core/cmd/key_store_authenticator.go b/core/cmd/key_store_authenticator.go index 6ad4b0ef2ba..7833566fcdc 100644 --- a/core/cmd/key_store_authenticator.go +++ b/core/cmd/key_store_authenticator.go @@ -17,11 +17,11 @@ type TerminalKeyStoreAuthenticator struct { Prompter Prompter } -type keystorePassword interface { +type KeystorePassword interface { Keystore() string } -func (auth TerminalKeyStoreAuthenticator) authenticate(ctx context.Context, keyStore keystore.Master, password keystorePassword) error { +func (auth TerminalKeyStoreAuthenticator) Authenticate(ctx context.Context, keyStore keystore.Master, password KeystorePassword) error { isEmpty, err := keyStore.IsEmpty(ctx) if err != nil { return errors.Wrap(err, "error determining if keystore is empty") diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 393c828afd1..9d92ddcf76e 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -66,7 +66,7 @@ var ( grpcOpts loop.GRPCOpts ) -func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTelemetry config.Telemetry, lggr logger.Logger) error { +func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTelemetry config.Telemetry, lggr logger.Logger, csaPubKeyHex string, beholderAuthHeaders map[string]string) error { // Avoid double initializations, but does not prevent relay methods from being called multiple times. var err error initGlobalsOnce.Do(func() { @@ -104,6 +104,8 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme OtelExporterGRPCEndpoint: cfgTelemetry.OtelExporterGRPCEndpoint(), ResourceAttributes: attributes, TraceSampleRatio: cfgTelemetry.TraceSampleRatio(), + AuthPublicKeyHex: csaPubKeyHex, + AuthHeaders: beholderAuthHeaders, } if tracingCfg.Enabled { clientCfg.TraceSpanExporter, err = tracingCfg.NewSpanExporter() @@ -174,19 +176,14 @@ func (s *Shell) configExitErr(validateFn func() error) cli.ExitCoder { // AppFactory implements the NewApplication method. type AppFactory interface { - NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB) (chainlink.Application, error) + NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (chainlink.Application, error) } // ChainlinkAppFactory is used to create a new Application. type ChainlinkAppFactory struct{} // NewApplication returns a new instance of the node with the given config. -func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB) (app chainlink.Application, err error) { - err = initGlobals(cfg.Prometheus(), cfg.Tracing(), cfg.Telemetry(), appLggr) - if err != nil { - appLggr.Errorf("Failed to initialize globals: %v", err) - } - +func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (app chainlink.Application, err error) { err = migrate.SetMigrationENVVars(cfg) if err != nil { return nil, err @@ -198,11 +195,31 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } ds := sqlutil.WrapDataSource(db, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL)) - keyStore := keystore.New(ds, utils.GetScryptParams(cfg), appLggr) + + err = keyStoreAuthenticator.Authenticate(ctx, keyStore, cfg.Password()) + if err != nil { + return nil, errors.Wrap(err, "error authenticating keystore") + } + + err = keyStore.CSA().EnsureKey(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to ensure CSA key") + } + + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) + if err != nil { + return nil, errors.Wrap(err, "failed to build Beholder auth") + } + + err = initGlobals(cfg.Prometheus(), cfg.Tracing(), cfg.Telemetry(), appLggr, csaPubKeyHex, beholderAuthHeaders) + if err != nil { + appLggr.Errorf("Failed to initialize globals: %v", err) + } + mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) - loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing(), cfg.Telemetry()) + loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex) mercuryPool := wsrpc.NewPool(appLggr, cache.Config{ LatestReportTTL: cfg.Mercury().Cache().LatestReportTTL(), diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 689e7d27d26..50411e10d42 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -382,18 +382,13 @@ func (s *Shell) runNode(c *cli.Context) error { // From now on, DB locks and DB connection will be released on every return. // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. - app, err := s.AppFactory.NewApplication(rootCtx, s.Config, s.Logger, ldb.DB()) + app, err := s.AppFactory.NewApplication(rootCtx, s.Config, s.Logger, ldb.DB(), s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } // Local shell initialization always uses local auth users table for admin auth authProviderORM := app.BasicAdminUsersORM() - keyStore := app.GetKeyStore() - err = s.KeyStoreAuthenticator.authenticate(rootCtx, keyStore, s.Config.Password()) - if err != nil { - return errors.Wrap(err, "error authenticating keystore") - } legacyEVMChains := app.GetRelayers().LegacyEVMChains() @@ -634,7 +629,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { } defer lggr.ErrorIfFn(db.Close, "Error closing db") - app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, db) + app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, db, s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } @@ -1281,7 +1276,7 @@ func (s *Shell) RemoveBlocks(c *cli.Context) error { // From now on, DB locks and DB connection will be released on every return. // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. - app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, ldb.DB()) + app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, ldb.DB(), s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 79d2b9f07a6..78254c0279e 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -46,7 +46,7 @@ import ( func genTestEVMRelayers(t *testing.T, opts legacyevm.ChainRelayOpts, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { f := chainlink.RelayerFactory{ Logger: opts.Logger, - LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing(), opts.AppConfig.Telemetry()), + LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing(), opts.AppConfig.Telemetry(), nil, ""), CapabilitiesRegistry: capabilities.NewRegistry(opts.Logger), } @@ -122,7 +122,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { Config: cfg, FallbackAPIInitializer: apiPrompt, Runner: cltest.EmptyRunner{}, - AppFactory: cltest.InstanceAppFactory{App: app}, + AppFactory: cltest.InstanceAppFactoryWithKeystoreMock{App: app}, Logger: lggr, } diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index a93be2fb9ea..13b914ba1c7 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -351,7 +351,7 @@ func TestNewUserCache(t *testing.T) { func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) - reg := plugins.NewLoopRegistry(lggr, nil, nil) + reg := plugins.NewLoopRegistry(lggr, nil, nil, nil, "") ks := mocks.NewSolana(t) // config 3 chains but only enable 2 => should only be 2 relayer @@ -466,7 +466,7 @@ func TestSetupSolanaRelayer(t *testing.T) { func TestSetupStarkNetRelayer(t *testing.T) { lggr := logger.TestLogger(t) - reg := plugins.NewLoopRegistry(lggr, nil, nil) + reg := plugins.NewLoopRegistry(lggr, nil, nil, nil, "") ks := mocks.NewStarkNet(t) // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index a858fc1d508..5ff48549490 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -394,7 +394,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn keyStore := keystore.NewInMemory(ds, utils.FastScryptParams, lggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) - loopRegistry := plugins.NewLoopRegistry(lggr, nil, nil) + loopRegistry := plugins.NewLoopRegistry(lggr, nil, nil, nil, "") mercuryPool := wsrpc.NewPool(lggr, cache.Config{ LatestReportTTL: cfg.Mercury().Cache().LatestReportTTL(), @@ -487,7 +487,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn RestrictedHTTPClient: c, UnrestrictedHTTPClient: c, SecretGenerator: MockSecretGenerator{}, - LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil), + LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil, nil, ""), MercuryPool: mercuryPool, CapabilitiesRegistry: capabilitiesRegistry, CapabilitiesDispatcher: dispatcher, diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go index fd01f72c131..b8bb4657056 100644 --- a/core/internal/cltest/mocks.go +++ b/core/internal/cltest/mocks.go @@ -10,11 +10,11 @@ import ( "testing" "time" + "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/jmoiron/sqlx" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -82,13 +82,27 @@ func (rm *RendererMock) Render(v interface{}, headers ...string) error { return nil } +type InstanceAppFactoryWithKeystoreMock struct { + App chainlink.Application +} + +// NewApplication creates a new application with specified config and calls the authenticate function of the keystore +func (f InstanceAppFactoryWithKeystoreMock) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, lggr logger.Logger, db *sqlx.DB, ks cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { + keyStore := f.App.GetKeyStore() + err := ks.Authenticate(ctx, keyStore, cfg.Password()) + if err != nil { + return nil, fmt.Errorf("error authenticating keystore: %w", err) + } + return f.App, nil +} + // InstanceAppFactory is an InstanceAppFactory type InstanceAppFactory struct { App chainlink.Application } // NewApplication creates a new application with specified config -func (f InstanceAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB) (chainlink.Application, error) { +func (f InstanceAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { return f.App, nil } @@ -96,7 +110,7 @@ type seededAppFactory struct { Application chainlink.Application } -func (s seededAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB) (chainlink.Application, error) { +func (s seededAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { return noopStopApplication{s.Application}, nil } diff --git a/core/scripts/go.mod b/core/scripts/go.mod index db35d5407a4..f0efc3cc962 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index cae3853c13c..8606d483969 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1092,8 +1092,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 h1:VfH/AW5NtTmroY9zz6OYCPFbFTqpMyJ2ubgT9ahYf3U= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff h1:Dduou3xzY4bVJPE9yIFW+Zfqrw7QG7ePPfauO+KY508= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 h1:sm8dL6NSFHmu2Bl17KhhfIwLQYWauxAFpBZ/w8WHuAA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 2c918b3a8d8..0b2352f67d4 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -294,7 +294,11 @@ func NewApplication(opts ApplicationOpts) (Application, error) { // we need to initialize in case we serve OCR2 LOOPs loopRegistry := opts.LoopRegistry if loopRegistry == nil { - loopRegistry = plugins.NewLoopRegistry(globalLogger, opts.Config.Tracing(), opts.Config.Telemetry()) + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) + if err != nil { + return nil, fmt.Errorf("could not build Beholder auth: %w", err) + } + loopRegistry = plugins.NewLoopRegistry(globalLogger, opts.Config.Tracing(), opts.Config.Telemetry(), beholderAuthHeaders, csaPubKeyHex) } // If the audit logger is enabled diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index e83c2881c93..a4bd8c168ba 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -176,7 +176,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { factory := chainlink.RelayerFactory{ Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil), + LoopRegistry: plugins.NewLoopRegistry(lggr, nil, nil, nil, ""), GRPCOpts: loop.GRPCOpts{}, CapabilitiesRegistry: capabilities.NewRegistry(lggr), } diff --git a/core/services/keystore/beholder.go b/core/services/keystore/beholder.go new file mode 100644 index 00000000000..40655cf0e82 --- /dev/null +++ b/core/services/keystore/beholder.go @@ -0,0 +1,19 @@ +package keystore + +import ( + "encoding/hex" + + "github.com/smartcontractkit/chainlink-common/pkg/beholder" +) + +func BuildBeholderAuth(keyStore Master) (authHeaders map[string]string, pubKeyHex string, err error) { + csaKeys, err := keyStore.CSA().GetAll() + if err != nil { + return nil, "", err + } + csaKey := csaKeys[0] + csaPrivKey := csaKey.Raw().Bytes() + authHeaders = beholder.BuildAuthHeaders(csaPrivKey) + pubKeyHex = hex.EncodeToString(csaKey.PublicKey) + return +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index 0b7f0de4d25..b34aab8decd 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -460,7 +460,10 @@ func setupNodeCCIP( }, CSAETHKeystore: simEthKeyStore, } - loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry()) + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) + require.NoError(t, err) + + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex) relayerFactory := chainlink.RelayerFactory{ Logger: lggr, LoopRegistry: loopRegistry, @@ -490,7 +493,7 @@ func setupNodeCCIP( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry()), + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex), }) require.NoError(t, err) require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go index b897d565bae..4118f158210 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go @@ -455,7 +455,11 @@ func setupNodeCCIP( }, CSAETHKeystore: simEthKeyStore, } - loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry()) + + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) + require.NoError(t, err) + + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex) relayerFactory := chainlink.RelayerFactory{ Logger: lggr, LoopRegistry: loopRegistry, @@ -485,7 +489,7 @@ func setupNodeCCIP( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry()), + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex), }) ctx := testutils.Context(t) require.NoError(t, err) diff --git a/core/web/loop_registry_internal_test.go b/core/web/loop_registry_internal_test.go index a02fa20802a..d1235cd09b4 100644 --- a/core/web/loop_registry_internal_test.go +++ b/core/web/loop_registry_internal_test.go @@ -38,7 +38,7 @@ func TestLoopRegistryServer_CantWriteToResponse(t *testing.T) { l, o := logger.TestLoggerObserved(t, zap.ErrorLevel) s := &LoopRegistryServer{ exposedPromPort: 1, - registry: plugins.NewLoopRegistry(l, nil, nil), + registry: plugins.NewLoopRegistry(l, nil, nil, nil, ""), logger: l.(logger.SugaredLogger), jsonMarshalFn: json.Marshal, } @@ -53,7 +53,7 @@ func TestLoopRegistryServer_CantMarshal(t *testing.T) { l, o := logger.TestLoggerObserved(t, zap.ErrorLevel) s := &LoopRegistryServer{ exposedPromPort: 1, - registry: plugins.NewLoopRegistry(l, nil, nil), + registry: plugins.NewLoopRegistry(l, nil, nil, nil, ""), logger: l.(logger.SugaredLogger), jsonMarshalFn: func(any) ([]byte, error) { return []byte(""), errors.New("can't unmarshal") diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index a2a690cbae5..90ad264faa9 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -145,10 +145,17 @@ func NewNode( CSAETHKeystore: kStore, } + // Build Beholder auth + ctx := tests.Context(t) + require.NoError(t, master.Unlock(ctx, "password")) + require.NoError(t, master.CSA().EnsureKey(ctx)) + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(master) + require.NoError(t, err) + // Build relayer factory with EVM. relayerFactory := chainlink.RelayerFactory{ Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing(), cfg.Telemetry()), + LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex), GRPCOpts: loop.GRPCOpts{}, CapabilitiesRegistry: capabilities.NewRegistry(lggr), } @@ -168,7 +175,7 @@ func NewNode( RestrictedHTTPClient: &http.Client{}, AuditLogger: audit.NoopLogger, MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing(), cfg.Telemetry()), + LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing(), cfg.Telemetry(), beholderAuthHeaders, csaPubKeyHex), }) require.NoError(t, err) t.Cleanup(func() { @@ -193,7 +200,6 @@ type Keys struct { func CreateKeys(t *testing.T, app chainlink.Application, chains map[uint64]EVMChain) Keys { ctx := tests.Context(t) - require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) _, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) diff --git a/deployment/go.mod b/deployment/go.mod index 52f6c7218b2..727e11215c8 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -24,7 +24,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index 3fc2bb5e63c..08402cd426d 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1384,8 +1384,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 h1:VfH/AW5NtTmroY9zz6OYCPFbFTqpMyJ2ubgT9ahYf3U= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff h1:Dduou3xzY4bVJPE9yIFW+Zfqrw7QG7ePPfauO+KY508= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 h1:sm8dL6NSFHmu2Bl17KhhfIwLQYWauxAFpBZ/w8WHuAA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/go.mod b/go.mod index c1d12475461..2aa832aaf25 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e github.com/smartcontractkit/chainlink-feeds v0.1.1 diff --git a/go.sum b/go.sum index ad233fa5104..08609453b6c 100644 --- a/go.sum +++ b/go.sum @@ -1077,8 +1077,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 h1:VfH/AW5NtTmroY9zz6OYCPFbFTqpMyJ2ubgT9ahYf3U= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff h1:Dduou3xzY4bVJPE9yIFW+Zfqrw7QG7ePPfauO+KY508= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 h1:sm8dL6NSFHmu2Bl17KhhfIwLQYWauxAFpBZ/w8WHuAA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f8587bf1b21..96e35773812 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -37,7 +37,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index f4d528be2dd..849746c7262 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1405,8 +1405,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 h1:VfH/AW5NtTmroY9zz6OYCPFbFTqpMyJ2ubgT9ahYf3U= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff h1:Dduou3xzY4bVJPE9yIFW+Zfqrw7QG7ePPfauO+KY508= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 h1:sm8dL6NSFHmu2Bl17KhhfIwLQYWauxAFpBZ/w8WHuAA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 8696f24a39a..0af0a8339fc 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,7 +17,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 5cdd3f0c7b9..2f574a6a744 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1394,8 +1394,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422 h1:VfH/AW5NtTmroY9zz6OYCPFbFTqpMyJ2ubgT9ahYf3U= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241106140121-4c9ee21ab422/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff h1:Dduou3xzY4bVJPE9yIFW+Zfqrw7QG7ePPfauO+KY508= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108143808-44ef01dbdeff/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2 h1:sm8dL6NSFHmu2Bl17KhhfIwLQYWauxAFpBZ/w8WHuAA= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241108204352-914b88b62cf2/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/plugins/loop_registry.go b/plugins/loop_registry.go index 51c6310ffa7..c0c2bc909bf 100644 --- a/plugins/loop_registry.go +++ b/plugins/loop_registry.go @@ -27,17 +27,21 @@ type LoopRegistry struct { mu sync.Mutex registry map[string]*RegisteredLoop - lggr logger.Logger - cfgTracing config.Tracing - cfgTelemetry config.Telemetry + lggr logger.Logger + cfgTracing config.Tracing + cfgTelemetry config.Telemetry + telemetryAuthHeaders map[string]string + telemetryAuthPubKeyHex string } -func NewLoopRegistry(lggr logger.Logger, tracing config.Tracing, telemetry config.Telemetry) *LoopRegistry { +func NewLoopRegistry(lggr logger.Logger, tracing config.Tracing, telemetry config.Telemetry, telemetryAuthHeaders map[string]string, telemetryAuthPubKeyHex string) *LoopRegistry { return &LoopRegistry{ - registry: map[string]*RegisteredLoop{}, - lggr: logger.Named(lggr, "LoopRegistry"), - cfgTracing: tracing, - cfgTelemetry: telemetry, + registry: map[string]*RegisteredLoop{}, + lggr: logger.Named(lggr, "LoopRegistry"), + cfgTracing: tracing, + cfgTelemetry: telemetry, + telemetryAuthHeaders: telemetryAuthHeaders, + telemetryAuthPubKeyHex: telemetryAuthPubKeyHex, } } @@ -74,10 +78,16 @@ func (m *LoopRegistry) Register(id string) (*RegisteredLoop, error) { envCfg.TelemetryCACertFile = m.cfgTelemetry.CACertFile() envCfg.TelemetryAttributes = m.cfgTelemetry.ResourceAttributes() envCfg.TelemetryTraceSampleRatio = m.cfgTelemetry.TraceSampleRatio() + envCfg.TelemetryAuthPubKeyHex = m.telemetryAuthPubKeyHex + } + m.lggr.Debugf("Registered loopp %q with config %v, port %d", id, envCfg, envCfg.PrometheusPort) + + // Add auth header after logging config + if m.cfgTelemetry != nil { + envCfg.TelemetryAuthHeaders = m.telemetryAuthHeaders } m.registry[id] = &RegisteredLoop{Name: id, EnvCfg: envCfg} - m.lggr.Debugf("Registered loopp %q with config %v, port %d", id, envCfg, envCfg.PrometheusPort) return m.registry[id], nil } diff --git a/plugins/loop_registry_test.go b/plugins/loop_registry_test.go index 84b6b0cefc9..1ce293e6a76 100644 --- a/plugins/loop_registry_test.go +++ b/plugins/loop_registry_test.go @@ -11,7 +11,7 @@ import ( func TestPluginPortManager(t *testing.T) { // register one - m := NewLoopRegistry(logger.TestLogger(t), nil, nil) + m := NewLoopRegistry(logger.TestLogger(t), nil, nil, nil, "") pFoo, err := m.Register("foo") require.NoError(t, err) require.Equal(t, "foo", pFoo.Name)