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`:
Directory to mount to the wasm guest.
`--experimental.localplugins.<name>.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.<name>.settings.mounts`:
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`:
plugin's version.

View File

@ -348,6 +348,9 @@ Environment variables to forward to the wasm guest.
`TRAEFIK_EXPERIMENTAL_LOCALPLUGINS_<NAME>_SETTINGS_MOUNTS`:
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`:
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`:
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`:
plugin's version.

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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"`
}