Ability to enable unsafe in yaegi through plugin manifest

This commit is contained in:
Ryan Melendez 2025-04-25 05:26:04 -04:00 committed by GitHub
parent a092c4f535
commit 8f37c8f0c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 10 deletions

View File

@ -348,6 +348,9 @@ Environment variables to forward to the wasm guest.
`--experimental.localplugins.<name>.settings.mounts`: `--experimental.localplugins.<name>.settings.mounts`:
Directory to mount to the wasm guest. Directory to mount to the wasm guest.
`--experimental.localplugins.<name>.settings.useunsafe`:
Allow the plugin to use unsafe package. (Default: ```false```)
`--experimental.otlplogs`: `--experimental.otlplogs`:
Enables the OpenTelemetry logs integration. (Default: ```false```) Enables the OpenTelemetry logs integration. (Default: ```false```)
@ -363,6 +366,9 @@ Environment variables to forward to the wasm guest.
`--experimental.plugins.<name>.settings.mounts`: `--experimental.plugins.<name>.settings.mounts`:
Directory to mount to the wasm guest. Directory to mount to the wasm guest.
`--experimental.plugins.<name>.settings.useunsafe`:
Allow the plugin to use unsafe package. (Default: ```false```)
`--experimental.plugins.<name>.version`: `--experimental.plugins.<name>.version`:
plugin's version. plugin's version.

View File

@ -348,6 +348,9 @@ Environment variables to forward to the wasm guest.
`TRAEFIK_EXPERIMENTAL_LOCALPLUGINS_<NAME>_SETTINGS_MOUNTS`: `TRAEFIK_EXPERIMENTAL_LOCALPLUGINS_<NAME>_SETTINGS_MOUNTS`:
Directory to mount to the wasm guest. Directory to mount to the wasm guest.
`TRAEFIK_EXPERIMENTAL_LOCALPLUGINS_<NAME>_SETTINGS_USEUNSAFE`:
Allow the plugin to use unsafe package. (Default: ```false```)
`TRAEFIK_EXPERIMENTAL_OTLPLOGS`: `TRAEFIK_EXPERIMENTAL_OTLPLOGS`:
Enables the OpenTelemetry logs integration. (Default: ```false```) Enables the OpenTelemetry logs integration. (Default: ```false```)
@ -363,6 +366,9 @@ Environment variables to forward to the wasm guest.
`TRAEFIK_EXPERIMENTAL_PLUGINS_<NAME>_SETTINGS_MOUNTS`: `TRAEFIK_EXPERIMENTAL_PLUGINS_<NAME>_SETTINGS_MOUNTS`:
Directory to mount to the wasm guest. Directory to mount to the wasm guest.
`TRAEFIK_EXPERIMENTAL_PLUGINS_<NAME>_SETTINGS_USEUNSAFE`:
Allow the plugin to use unsafe package. (Default: ```false```)
`TRAEFIK_EXPERIMENTAL_PLUGINS_<NAME>_VERSION`: `TRAEFIK_EXPERIMENTAL_PLUGINS_<NAME>_VERSION`:
plugin's version. plugin's version.

View File

@ -575,23 +575,27 @@
[experimental.plugins.Descriptor0.settings] [experimental.plugins.Descriptor0.settings]
envs = ["foobar", "foobar"] envs = ["foobar", "foobar"]
mounts = ["foobar", "foobar"] mounts = ["foobar", "foobar"]
useUnsafe = true
[experimental.plugins.Descriptor1] [experimental.plugins.Descriptor1]
moduleName = "foobar" moduleName = "foobar"
version = "foobar" version = "foobar"
[experimental.plugins.Descriptor1.settings] [experimental.plugins.Descriptor1.settings]
envs = ["foobar", "foobar"] envs = ["foobar", "foobar"]
mounts = ["foobar", "foobar"] mounts = ["foobar", "foobar"]
useUnsafe = true
[experimental.localPlugins] [experimental.localPlugins]
[experimental.localPlugins.LocalDescriptor0] [experimental.localPlugins.LocalDescriptor0]
moduleName = "foobar" moduleName = "foobar"
[experimental.localPlugins.LocalDescriptor0.settings] [experimental.localPlugins.LocalDescriptor0.settings]
envs = ["foobar", "foobar"] envs = ["foobar", "foobar"]
mounts = ["foobar", "foobar"] mounts = ["foobar", "foobar"]
useUnsafe = true
[experimental.localPlugins.LocalDescriptor1] [experimental.localPlugins.LocalDescriptor1]
moduleName = "foobar" moduleName = "foobar"
[experimental.localPlugins.LocalDescriptor1.settings] [experimental.localPlugins.LocalDescriptor1.settings]
envs = ["foobar", "foobar"] envs = ["foobar", "foobar"]
mounts = ["foobar", "foobar"] mounts = ["foobar", "foobar"]
useUnsafe = true
[experimental.fastProxy] [experimental.fastProxy]
debug = true debug = true

View File

@ -628,6 +628,7 @@ experimental:
mounts: mounts:
- foobar - foobar
- foobar - foobar
useUnsafe: true
Descriptor1: Descriptor1:
moduleName: foobar moduleName: foobar
version: foobar version: foobar
@ -638,6 +639,7 @@ experimental:
mounts: mounts:
- foobar - foobar
- foobar - foobar
useUnsafe: true
localPlugins: localPlugins:
LocalDescriptor0: LocalDescriptor0:
moduleName: foobar moduleName: foobar
@ -648,6 +650,7 @@ experimental:
mounts: mounts:
- foobar - foobar
- foobar - foobar
useUnsafe: true
LocalDescriptor1: LocalDescriptor1:
moduleName: foobar moduleName: foobar
settings: settings:
@ -657,6 +660,7 @@ experimental:
mounts: mounts:
- foobar - foobar
- foobar - foobar
useUnsafe: true
abortOnPluginFailure: true abortOnPluginFailure: true
fastProxy: fastProxy:
debug: true debug: true

View File

@ -60,7 +60,7 @@ func NewBuilder(client *Client, plugins map[string]Descriptor, localPlugins map[
pb.middlewareBuilders[pName] = middleware pb.middlewareBuilders[pName] = middleware
case typeProvider: case typeProvider:
pBuilder, err := newProviderBuilder(logCtx, manifest, client.GoPath()) pBuilder, err := newProviderBuilder(logCtx, manifest, client.GoPath(), desc.Settings)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: %w", desc.ModuleName, err) 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 pb.middlewareBuilders[pName] = middleware
case typeProvider: case typeProvider:
builder, err := newProviderBuilder(logCtx, manifest, localGoPath) builder, err := newProviderBuilder(logCtx, manifest, localGoPath, desc.Settings)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: %w", desc.ModuleName, err) 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) return newWasmMiddlewareBuilder(goPath, moduleName, wasmPath, settings)
case runtimeYaegi, "": case runtimeYaegi, "":
i, err := newInterpreter(ctx, goPath, manifest.Import) i, err := newInterpreter(ctx, goPath, manifest, settings)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create Yaegi interpreter: %w", err) 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 { switch manifest.Runtime {
case runtimeYaegi, "": case runtimeYaegi, "":
i, err := newInterpreter(ctx, goPath, manifest.Import) i, err := newInterpreter(ctx, goPath, manifest, settings)
if err != nil { if err != nil {
return providerBuilder{}, err return providerBuilder{}, err
} }

View File

@ -2,6 +2,7 @@ package plugins
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
@ -15,6 +16,7 @@ import (
"github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib" "github.com/traefik/yaegi/stdlib"
"github.com/traefik/yaegi/stdlib/unsafe"
) )
type yaegiMiddlewareBuilder struct { 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) 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{ i := interp.New(interp.Options{
GoPath: goPath, GoPath: goPath,
Env: os.Environ(), 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) 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()) err = i.Use(ppSymbols())
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load provider symbols: %w", err) 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 { 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 return i, nil

View File

@ -11,8 +11,9 @@ const (
) )
type Settings struct { type Settings struct {
Envs []string `description:"Environment variables to forward to the wasm guest." json:"envs,omitempty" toml:"envs,omitempty" yaml:"envs,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"` 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. // Descriptor The static part of a plugin configuration.
@ -46,6 +47,7 @@ type Manifest struct {
BasePkg string `yaml:"basePkg"` BasePkg string `yaml:"basePkg"`
Compatibility string `yaml:"compatibility"` Compatibility string `yaml:"compatibility"`
Summary string `yaml:"summary"` Summary string `yaml:"summary"`
UseUnsafe bool `yaml:"useUnsafe"`
TestData map[string]interface{} `yaml:"testData"` TestData map[string]interface{} `yaml:"testData"`
} }