diff --git a/README.md b/README.md index 4bacfaec..89a98114 100644 --- a/README.md +++ b/README.md @@ -454,6 +454,9 @@ the WebAssembly plugin is required, then the NRI provides a host function helper [`Log`](https://github.com/containerd/nri/blob/8ebdb076ea6aa524094a7f1c2c9ca31c30852328/plugins/wasm/plugin.go#L31-L36) for that. +WebAssembly support is enabled by default. It can be disabled at compile +time using the `nri_no_wasm` build tag. + ## Security Considerations From a security perspective NRI plugins should be considered part of the diff --git a/pkg/adaptation/adaptation.go b/pkg/adaptation/adaptation.go index 367c04e3..54518e11 100644 --- a/pkg/adaptation/adaptation.go +++ b/pkg/adaptation/adaptation.go @@ -32,8 +32,6 @@ import ( "github.com/containerd/nri/pkg/log" validator "github.com/containerd/nri/plugins/default-validator/builtin" "github.com/containerd/ttrpc" - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" "google.golang.org/protobuf/proto" ) @@ -80,6 +78,9 @@ type Adaptation struct { var ( // Used instead of nil Context in logging. noCtx = context.TODO() + + // ErrWasmDisabled is returned for WASM initialization if WASM support is disabled. + ErrWasmDisabled = errors.New("WASM support is disabled (at build time)") ) // Option to apply to the NRI runtime. @@ -155,23 +156,12 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) return nil, fmt.Errorf("failed to create NRI adaptation, nil UpdateFn") } - wasmWithCloseOnContextDone := func(ctx context.Context) (wazero.Runtime, error) { - var ( - cfg = wazero.NewRuntimeConfig().WithCloseOnContextDone(true) - r = wazero.NewRuntimeWithConfig(ctx, cfg) - ) - if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil { + wasmService, err := getWasmService() + if err != nil { + log.Errorf(noCtx, "failed to initialize WASM support: %v", err) + if !errors.Is(err, ErrWasmDisabled) { return nil, err } - return r, nil - } - - wasmPlugins, err := api.NewPluginPlugin( - context.Background(), - api.WazeroRuntime(wasmWithCloseOnContextDone), - ) - if err != nil { - return nil, fmt.Errorf("unable to initialize WASM service: %w", err) } r := &Adaptation{ @@ -183,7 +173,7 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) dropinPath: DefaultPluginConfigPath, socketPath: DefaultSocketPath, syncLock: sync.RWMutex{}, - wasmService: wasmPlugins, + wasmService: wasmService, } for _, o := range opts { diff --git a/pkg/adaptation/plugin.go b/pkg/adaptation/plugin.go index 80e5555b..50fbebfe 100644 --- a/pkg/adaptation/plugin.go +++ b/pkg/adaptation/plugin.go @@ -104,6 +104,10 @@ func (r *Adaptation) newLaunchedPlugin(dir, idx, base, cfg string) (p *plugin, r fullPath := filepath.Join(dir, name) if isWasm(fullPath) { + if r.wasmService == nil { + return nil, fmt.Errorf("can't load WASM plugin %s: no WASM support", fullPath) + } + log.Infof(noCtx, "Found WASM plugin: %s", fullPath) wasm, err := r.wasmService.Load(context.Background(), fullPath, wasmHostFunctions{}) if err != nil { diff --git a/pkg/adaptation/wasm-disabled.go b/pkg/adaptation/wasm-disabled.go new file mode 100644 index 00000000..7779008d --- /dev/null +++ b/pkg/adaptation/wasm-disabled.go @@ -0,0 +1,27 @@ +//go:build nri_no_wasm + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package adaptation + +import ( + "github.com/containerd/nri/pkg/api" +) + +func getWasmService() (*api.PluginPlugin, error) { + return nil, ErrWasmDisabled +} diff --git a/pkg/adaptation/wasm-enabled.go b/pkg/adaptation/wasm-enabled.go new file mode 100644 index 00000000..ada58a3a --- /dev/null +++ b/pkg/adaptation/wasm-enabled.go @@ -0,0 +1,51 @@ +//go:build !nri_no_wasm + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package adaptation + +import ( + "context" + "fmt" + + "github.com/containerd/nri/pkg/api" + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" +) + +func getWasmService() (*api.PluginPlugin, error) { + wasmWithCloseOnContextDone := func(ctx context.Context) (wazero.Runtime, error) { + var ( + cfg = wazero.NewRuntimeConfig().WithCloseOnContextDone(true) + r = wazero.NewRuntimeWithConfig(ctx, cfg) + ) + if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil { + return nil, err + } + return r, nil + } + + wasmPlugins, err := api.NewPluginPlugin( + context.Background(), + api.WazeroRuntime(wasmWithCloseOnContextDone), + ) + if err != nil { + return nil, fmt.Errorf("unable to initialize WASM service: %w", err) + } + + return wasmPlugins, nil +}