From 86a5602d95bc973a45521d7368865d409d09617a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Gro=C3=9Fmann?= Date: Tue, 22 Jul 2025 09:59:47 +0200 Subject: [PATCH] feat(sdk): option to disable engine plugins --- engine/README.md | 2 +- engine/adaptation.go | 13 +++++++++- engine/adaptation_test.go | 53 +++++++++++++++++++++++++++++++++++++-- engine/engine.go | 6 +++-- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/engine/README.md b/engine/README.md index 52cce7d5..cea1deb5 100644 --- a/engine/README.md +++ b/engine/README.md @@ -21,5 +21,5 @@ The two main tasks of the engine are: - [ ] configuration - [ ] retry behaviour when plugins crash - [ ] logging - - [ ] permanently disable engine launched plugins + - [x] permanently disable engine launched plugins - [x] permanently disable externally launched plugins \ No newline at end of file diff --git a/engine/adaptation.go b/engine/adaptation.go index ad95bad2..84a73ea8 100644 --- a/engine/adaptation.go +++ b/engine/adaptation.go @@ -37,6 +37,7 @@ type config struct { socketPath string plugins map[string]Plugin dynamicPluginsDisabled bool + enginePluginsDisabled bool } type adaptation struct { @@ -73,13 +74,23 @@ func WithPlugins(plugins map[string]Plugin) Option { } } -func WithDisableDynamicPlugins() Option { +// WithExternallyLaunchedPluginsDisabled disables accepting plugin registration requests coming +// from plugins that have been launched externally +func WithExternallyLaunchedPluginsDisabled() Option { return func(r *config) error { r.dynamicPluginsDisabled = true return nil } } +// WithEngineLaunchedPluginsDisabled disables launching any plugins from the plugin directory +func WithEngineLaunchedPluginsDisabled() Option { + return func(r *config) error { + r.enginePluginsDisabled = true + return nil + } +} + // New creates a new NRI Runtime. func New(name, version string, opts ...Option) (Engine, error) { cfg := &config{ diff --git a/engine/adaptation_test.go b/engine/adaptation_test.go index 24242ede..5a47d3b3 100644 --- a/engine/adaptation_test.go +++ b/engine/adaptation_test.go @@ -112,12 +112,12 @@ func Test_SecretsEngine(t *testing.T) { }) } -func TestWithDisableDynamicPlugins(t *testing.T) { +func TestWithDynamicPluginsDisabled(t *testing.T) { path := filepath.Join(t.TempDir(), "e.sock") e, err := New("test-engine", "test-version", WithSocketPath(path), WithPluginPath(t.TempDir()), - WithDisableDynamicPlugins(), + WithExternallyLaunchedPluginsDisabled(), ) assert.NoError(t, err) require.NoError(t, e.Start()) @@ -130,6 +130,55 @@ func TestWithDisableDynamicPlugins(t *testing.T) { assert.ErrorContains(t, err, "external plugin rejected") } +func TestWithEnginePluginsDisabled(t *testing.T) { + tests := []struct { + name string + shouldGetSecretFromExternalPlugin bool + extraOption Option + }{ + { + name: "external plugins enabled", + shouldGetSecretFromExternalPlugin: true, + }, + { + name: "external plugins disabled", + extraOption: WithEngineLaunchedPluginsDisabled(), + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + dir := createDummyPlugins(t, dummyPlugins{okPlugins: []string{"plugin-foo"}}) + socketPath := "foo.sock" + options := []Option{ + WithSocketPath(socketPath), + WithPluginPath(dir), + WithExternallyLaunchedPluginsDisabled(), + WithPlugins(map[string]Plugin{"my-builtin": &mockInternalPlugin{pattern: "*", secrets: map[secrets.ID]string{"my-secret": "some-value"}}}), + } + if test.extraOption != nil { + options = append(options, test.extraOption) + } + e, err := New("test-engine", "test-version", options...) + assert.NoError(t, err) + require.NoError(t, e.Start()) + t.Cleanup(func() { assert.NoError(t, e.Stop()) }) + c, err := client.New(client.WithSocketPath(socketPath)) + require.NoError(t, err) + _, err = c.GetSecret(t.Context(), secrets.Request{ID: "foo"}) + if test.shouldGetSecretFromExternalPlugin { + assert.NoError(t, err) + } else { + assert.Error(t, err) + } + mySecret, err := c.GetSecret(t.Context(), secrets.Request{ID: "my-secret"}) + assert.NoError(t, err) + assert.Equal(t, secrets.ID("my-secret"), mySecret.ID) + assert.Equal(t, "some-value", string(mySecret.Value)) + assert.Equal(t, "my-builtin", mySecret.Provider) + }) + } +} + type externalPluginTestConfig struct { socketPath string name string diff --git a/engine/engine.go b/engine/engine.go index 7527ed81..917e6e29 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -35,8 +35,10 @@ func newEngine(cfg config) (io.Closer, error) { reg := &manager{} startBuiltins(context.Background(), reg, cfg.plugins) - if err := startPlugins(cfg, reg); err != nil { - return nil, err + if !cfg.enginePluginsDisabled { + if err := startPlugins(cfg, reg); err != nil { + return nil, err + } } m := sync.Mutex{} stopPlugins := func() error {