diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 8aff56bd9..92902ec2e 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -348,6 +348,9 @@ Environment variables to forward to the wasm guest. `--experimental.localplugins..settings.mounts`: Directory to mount to the wasm guest. +`--experimental.localplugins..settings.useunsafe`: +Allow the plugin to use unsafe package. (Default: ```false```) + `--experimental.otlplogs`: Enables the OpenTelemetry logs integration. (Default: ```false```) @@ -363,6 +366,9 @@ Environment variables to forward to the wasm guest. `--experimental.plugins..settings.mounts`: Directory to mount to the wasm guest. +`--experimental.plugins..settings.useunsafe`: +Allow the plugin to use unsafe package. (Default: ```false```) + `--experimental.plugins..version`: plugin's version. diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 172f457a6..c0f46f53d 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -348,6 +348,9 @@ Environment variables to forward to the wasm guest. `TRAEFIK_EXPERIMENTAL_LOCALPLUGINS__SETTINGS_MOUNTS`: Directory to mount to the wasm guest. +`TRAEFIK_EXPERIMENTAL_LOCALPLUGINS__SETTINGS_USEUNSAFE`: +Allow the plugin to use unsafe package. (Default: ```false```) + `TRAEFIK_EXPERIMENTAL_OTLPLOGS`: Enables the OpenTelemetry logs integration. (Default: ```false```) @@ -363,6 +366,9 @@ Environment variables to forward to the wasm guest. `TRAEFIK_EXPERIMENTAL_PLUGINS__SETTINGS_MOUNTS`: Directory to mount to the wasm guest. +`TRAEFIK_EXPERIMENTAL_PLUGINS__SETTINGS_USEUNSAFE`: +Allow the plugin to use unsafe package. (Default: ```false```) + `TRAEFIK_EXPERIMENTAL_PLUGINS__VERSION`: plugin's version. diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 28dbd6bf3..204fead53 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -575,23 +575,27 @@ [experimental.plugins.Descriptor0.settings] envs = ["foobar", "foobar"] mounts = ["foobar", "foobar"] + useUnsafe = true [experimental.plugins.Descriptor1] moduleName = "foobar" version = "foobar" [experimental.plugins.Descriptor1.settings] envs = ["foobar", "foobar"] mounts = ["foobar", "foobar"] + useUnsafe = true [experimental.localPlugins] [experimental.localPlugins.LocalDescriptor0] moduleName = "foobar" [experimental.localPlugins.LocalDescriptor0.settings] envs = ["foobar", "foobar"] mounts = ["foobar", "foobar"] + useUnsafe = true [experimental.localPlugins.LocalDescriptor1] moduleName = "foobar" [experimental.localPlugins.LocalDescriptor1.settings] envs = ["foobar", "foobar"] mounts = ["foobar", "foobar"] + useUnsafe = true [experimental.fastProxy] debug = true diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index c57ea5186..2c9fb3223 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -628,6 +628,7 @@ experimental: mounts: - foobar - foobar + useUnsafe: true Descriptor1: moduleName: foobar version: foobar @@ -638,6 +639,7 @@ experimental: mounts: - foobar - foobar + useUnsafe: true localPlugins: LocalDescriptor0: moduleName: foobar @@ -648,6 +650,7 @@ experimental: mounts: - foobar - foobar + useUnsafe: true LocalDescriptor1: moduleName: foobar settings: @@ -657,6 +660,7 @@ experimental: mounts: - foobar - foobar + useUnsafe: true abortOnPluginFailure: true fastProxy: debug: true diff --git a/pkg/plugins/builder.go b/pkg/plugins/builder.go index 9e47d134b..8559dec90 100644 --- a/pkg/plugins/builder.go +++ b/pkg/plugins/builder.go @@ -60,7 +60,7 @@ func NewBuilder(client *Client, plugins map[string]Descriptor, localPlugins map[ pb.middlewareBuilders[pName] = middleware case typeProvider: - pBuilder, err := newProviderBuilder(logCtx, manifest, client.GoPath()) + pBuilder, err := newProviderBuilder(logCtx, manifest, client.GoPath(), desc.Settings) if err != nil { return nil, fmt.Errorf("%s: %w", desc.ModuleName, err) } @@ -95,7 +95,7 @@ func NewBuilder(client *Client, plugins map[string]Descriptor, localPlugins map[ pb.middlewareBuilders[pName] = middleware case typeProvider: - builder, err := newProviderBuilder(logCtx, manifest, localGoPath) + builder, err := newProviderBuilder(logCtx, manifest, localGoPath, desc.Settings) if err != nil { return nil, fmt.Errorf("%s: %w", desc.ModuleName, err) } @@ -139,7 +139,7 @@ func newMiddlewareBuilder(ctx context.Context, goPath string, manifest *Manifest return newWasmMiddlewareBuilder(goPath, moduleName, wasmPath, settings) case runtimeYaegi, "": - i, err := newInterpreter(ctx, goPath, manifest.Import) + i, err := newInterpreter(ctx, goPath, manifest, settings) if err != nil { return nil, fmt.Errorf("failed to create Yaegi interpreter: %w", err) } @@ -151,10 +151,10 @@ func newMiddlewareBuilder(ctx context.Context, goPath string, manifest *Manifest } } -func newProviderBuilder(ctx context.Context, manifest *Manifest, goPath string) (providerBuilder, error) { +func newProviderBuilder(ctx context.Context, manifest *Manifest, goPath string, settings Settings) (providerBuilder, error) { switch manifest.Runtime { case runtimeYaegi, "": - i, err := newInterpreter(ctx, goPath, manifest.Import) + i, err := newInterpreter(ctx, goPath, manifest, settings) if err != nil { return providerBuilder{}, err } diff --git a/pkg/plugins/middlewareyaegi.go b/pkg/plugins/middlewareyaegi.go index 452f8713b..a23db53e7 100644 --- a/pkg/plugins/middlewareyaegi.go +++ b/pkg/plugins/middlewareyaegi.go @@ -2,6 +2,7 @@ package plugins import ( "context" + "errors" "fmt" "net/http" "os" @@ -15,6 +16,7 @@ import ( "github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/stdlib" + "github.com/traefik/yaegi/stdlib/unsafe" ) type yaegiMiddlewareBuilder struct { @@ -119,7 +121,7 @@ func (m *YaegiMiddleware) NewHandler(ctx context.Context, next http.Handler) (ht return m.builder.newHandler(ctx, next, m.config, m.middlewareName) } -func newInterpreter(ctx context.Context, goPath string, manifestImport string) (*interp.Interpreter, error) { +func newInterpreter(ctx context.Context, goPath string, manifest *Manifest, settings Settings) (*interp.Interpreter, error) { i := interp.New(interp.Options{ GoPath: goPath, Env: os.Environ(), @@ -132,14 +134,25 @@ func newInterpreter(ctx context.Context, goPath string, manifestImport string) ( return nil, fmt.Errorf("failed to load symbols: %w", err) } + if manifest.UseUnsafe && !settings.UseUnsafe { + return nil, errors.New("this plugin uses unsafe import. If you want to use it, you need to allow useUnsafe in the settings") + } + + if settings.UseUnsafe && manifest.UseUnsafe { + err := i.Use(unsafe.Symbols) + if err != nil { + return nil, fmt.Errorf("failed to load unsafe symbols: %w", err) + } + } + err = i.Use(ppSymbols()) if err != nil { return nil, fmt.Errorf("failed to load provider symbols: %w", err) } - _, err = i.Eval(fmt.Sprintf(`import "%s"`, manifestImport)) + _, err = i.Eval(fmt.Sprintf(`import "%s"`, manifest.Import)) if err != nil { - return nil, fmt.Errorf("failed to import plugin code %q: %w", manifestImport, err) + return nil, fmt.Errorf("failed to import plugin code %q: %w", manifest.Import, err) } return i, nil diff --git a/pkg/plugins/types.go b/pkg/plugins/types.go index 23254f7f7..ccae8dce4 100644 --- a/pkg/plugins/types.go +++ b/pkg/plugins/types.go @@ -11,8 +11,9 @@ const ( ) type Settings struct { - Envs []string `description:"Environment variables to forward to the wasm guest." json:"envs,omitempty" toml:"envs,omitempty" yaml:"envs,omitempty"` - Mounts []string `description:"Directory to mount to the wasm guest." json:"mounts,omitempty" toml:"mounts,omitempty" yaml:"mounts,omitempty"` + Envs []string `description:"Environment variables to forward to the wasm guest." json:"envs,omitempty" toml:"envs,omitempty" yaml:"envs,omitempty"` + Mounts []string `description:"Directory to mount to the wasm guest." json:"mounts,omitempty" toml:"mounts,omitempty" yaml:"mounts,omitempty"` + UseUnsafe bool `description:"Allow the plugin to use unsafe package." json:"useUnsafe,omitempty" toml:"useUnsafe,omitempty" yaml:"useUnsafe,omitempty"` } // Descriptor The static part of a plugin configuration. @@ -46,6 +47,7 @@ type Manifest struct { BasePkg string `yaml:"basePkg"` Compatibility string `yaml:"compatibility"` Summary string `yaml:"summary"` + UseUnsafe bool `yaml:"useUnsafe"` TestData map[string]interface{} `yaml:"testData"` }