plugin

package
v0.0.0-...-4e66fdd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2024 License: Apache-2.0 Imports: 11 Imported by: 0

README

Veraison Plugin Framework

Note: This section is primarily of interest to core Veraison developers. see here if you wish to learn how to implement plugins to support new attestation schemes.

Veraison services functionality can be extended via plugins. Extension points are defined via interfaces that embed plugin.IPluggable interface (which defines functionality common to all plugins. plugin.IPluggable implementations are managed via a plugin.IManager[I IPluggable], which allows obtaining plugin implementations either by name or media type.

Veraison plugin handling is implemented on top of HashiCorp go-plugin framework.

Defining new plugin types

All Veraison plugins must implement the IPluggable interface:


type IPluggable interface {
	GetName() string
	GetAttestationScheme() string
	GetSupportedMediaTypes() []string
}

A plugin implementation must have a unique name, and it may also advertise the media types it can handle.

Warning: Currently, Veraison doesn't support multiple plugins advertising the same media type. If a manager (see below) discovers a plugin that advertises a media type that has already been registered, it will return an error.

In order to define new extension points (plugin types) for Veraison, one needs to define a new interface embedding plugin.IPluggable, and provide an RPC channel for that interface.

package myplugin

import (
    "net/rpc"
    "github.com/veraison/plugin"
)

type IMyPlugin interface {
    plugin.IPluggable

    Method1()
}

var MyPluginRPC = &plugin.RPCChannel[IMyPlugin]{
    GetClient: func(c *rpc.Client) interface{} { return &PRCClient{client: c } },
    GetServer: func(i IMyPlugin) interface{} { return &PRCServer{Impl: i } },
}

type PRCClient {
    client *rpc.Client
}

type RPCServer struct {
    Impl IMyPlugin
}

// ---8<----------------------------------------------------------
// IMyPlugin implementations for RPCClient and RPCServer go below.
// ...

HashiCorp framework supports implementing RPC using net/rpc or gRPC. See here for further details.

Creating plugins

ℹ For the specifics of how to create implementations of the already defined IEndorsmentHandler and IEvidenceHandler Veraison plugins, see here.

Plugins are created by implementing the corresponding interface, registering this implementation under an appropriate name (matching the name the manager will look for on discovery -- see below), and serving the plugin inside main():

package main

import (
    "github.com/veraison/plugin"

    "myplugin" // see above
)

type Impl struct {}

func (o *Impl) GetName() string { return "my-implementation" }
func (o *Impl) GetAttestationScheme() string { return "my-scheme" }
func (o *Impl) GetSupportedMediaTypes() []string { return []string{"text/html"} }
func (o *Impl) Method1() {}

func main() {
    // "my-plugin" should match what the manager is looking for -- see below
    plugin.RegisterImplementation("my-plugin", &Impl{}, myplugin.MyPluginRPC)
    plugin.Serve()
}

Discovering and using plugins

In short, you create a manager using plugin.CreateGoPluginManager, specifying which plugins you want it to manage, and where to look for them, and then look up your plugin either via it's name or one of the media types it supports.

package main

import (
    "github.com/veraison/config"
    "github.com/veraison/log"
    "github.com/veraison/plugin"

    "myplugin" // see above
)

func main() {

    // Read configuration form a file using github.com/spf13/viper
    v, err := config.ReadRawConfig("", false)
    if err != nil {
            log.Fatalf("Could not read config sources: %v", err)
    }

    // Extract the sub-secition of config related to plugin management
    subs, err := config.GetSubs(v, "plugin")
    if err != nil {
            log.Fatal(err)
    }

    pluginManager, err := plugin.CreateGoPluginManager(
            subs["plugin"], log.Named("plugin"),
            // plugins must register themselves with type "my-plugin" -- see
            // above.
            "my-plugins", myplugin.MyPluginRPC)

    var impl myplugin.IMyPlugin

    // look up by name...
    imp, err = pluginManager.LookupByName("my-implementation")
    if err != nil {
            log.Fatal(err)
    }

    // ...or, alternatively, by media type
    imp, err = pluginManager.LookupByMediaType("test/html")
    if err != nil {
            log.Fatal(err)
    }

    // use your plugin
    impl.Method1()
}

Documentation

Overview

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Copyright 2023 Contributors to the Veraison project. SPDX-License-Identifier: Apache-2.0

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("plugin not found")

Functions

func DiscoverGoPlugin

func DiscoverGoPlugin[I IPluggable]() error

func DiscoverGoPluginUsing

func DiscoverGoPluginUsing[I IPluggable](o *GoPluginLoader) error

func GetGoPluginHandleByAttestationSchemeUsing

func GetGoPluginHandleByAttestationSchemeUsing[I IPluggable](
	ldr *GoPluginLoader,
	scheme string,
) (I, error)

func GetGoPluginHandleByMediaType

func GetGoPluginHandleByMediaType[I IPluggable](mediaType string) (I, error)

func GetGoPluginHandleByMediaTypeUsing

func GetGoPluginHandleByMediaTypeUsing[I IPluggable](
	ldr *GoPluginLoader,
	mediaType string,
) (I, error)

func GetGoPluginHandleByNameUsing

func GetGoPluginHandleByNameUsing[I IPluggable](ldr *GoPluginLoader, name string) (I, error)

func GetGoPluginLoadedAttestationSchemes

func GetGoPluginLoadedAttestationSchemes[I IPluggable](ldr *GoPluginLoader) []string

func GetRPCClient

func GetRPCClient[I IPluggable](name string, impl I, c *rpc.Client) interface{}

func GetRPCServer

func GetRPCServer[I IPluggable](name string, impl I) interface{}

func GetTypeName

func GetTypeName[I IPluggable]() string

func Init

func Init(m map[string]interface{}) error

func RegisterGoPlugin

func RegisterGoPlugin[I IPluggable](name string, ch *RPCChannel[I]) error

func RegisterGoPluginUsing

func RegisterGoPluginUsing[I IPluggable](
	loader *GoPluginLoader,
	name string,
	ch *RPCChannel[I],
) error

func RegisterImplementation

func RegisterImplementation[I IPluggable](name string, i I, ch *RPCChannel[I]) error

func Serve

func Serve()

Types

type GoPluginLoader

type GoPluginLoader struct {
	Location string
	// contains filtered or unexported fields
}

func CreateGoPluginLoader

func CreateGoPluginLoader(
	cfg map[string]interface{},
	logger *zap.SugaredLogger,
) (*GoPluginLoader, error)

func NewGoPluginLoader

func NewGoPluginLoader(logger *zap.SugaredLogger) *GoPluginLoader

func (*GoPluginLoader) Close

func (o *GoPluginLoader) Close()

func (*GoPluginLoader) GetRegisteredMediaTypes

func (o *GoPluginLoader) GetRegisteredMediaTypes() []string

func (*GoPluginLoader) GetRegisteredMediaTypesByPluginType

func (o *GoPluginLoader) GetRegisteredMediaTypesByPluginType(typeName string) []string

func (*GoPluginLoader) Init

func (o *GoPluginLoader) Init(m map[string]interface{}) error

type GoPluginLoaderConfig

type GoPluginLoaderConfig struct {
	Directory string `mapstructure:"dir"`
}

type GoPluginManager

type GoPluginManager[I IPluggable] struct {
	// contains filtered or unexported fields
}

func CreateGoPluginManager

func CreateGoPluginManager[I IPluggable](
	v *viper.Viper,
	logger *zap.SugaredLogger,
	name string,
	ch *RPCChannel[I],
) (*GoPluginManager[I], error)

func CreateGoPluginManagerWithLoader

func CreateGoPluginManagerWithLoader[I IPluggable](
	loader *GoPluginLoader,
	name string,
	logger *zap.SugaredLogger,
	ch *RPCChannel[I],
) (*GoPluginManager[I], error)

func NewGoPluginManager

func NewGoPluginManager[I IPluggable](
	loader *GoPluginLoader,
	logger *zap.SugaredLogger,
) *GoPluginManager[I]

func (*GoPluginManager[I]) Close

func (o *GoPluginManager[I]) Close() error

func (*GoPluginManager[I]) GetRegisteredAttestationSchemes

func (o *GoPluginManager[I]) GetRegisteredAttestationSchemes() []string

func (*GoPluginManager[I]) GetRegisteredMediaTypes

func (o *GoPluginManager[I]) GetRegisteredMediaTypes() []string

func (*GoPluginManager[I]) Init

func (o *GoPluginManager[I]) Init(name string, ch *RPCChannel[I]) error

func (*GoPluginManager[I]) IsRegisteredMediaType

func (o *GoPluginManager[I]) IsRegisteredMediaType(mediaType string) bool

func (*GoPluginManager[I]) LookupByAttestationScheme

func (o *GoPluginManager[I]) LookupByAttestationScheme(name string) (I, error)

func (*GoPluginManager[I]) LookupByMediaType

func (o *GoPluginManager[I]) LookupByMediaType(mediaType string) (I, error)

func (*GoPluginManager[I]) LookupByName

func (o *GoPluginManager[I]) LookupByName(name string) (I, error)

type IManager

type IManager[I IPluggable] interface {
	// Init initializes the manager, configuring the RPC channel that will
	// be used to communicate with plugins, and performing plugin
	// discovery.
	Init(name string, ch *RPCChannel[I]) error

	// Close terminates the manager, shutting down any current plugin
	// connections.
	Close() error

	// IsRegisteredMediaType returns true iff the provided mediaType has
	// been registered with that manager as handled by one of the
	// discovered plugins.
	IsRegisteredMediaType(mediaType string) bool

	// GetRegisteredMediaTypes returns a []string of media types that have
	// been registered with the manager by discovered plugins.
	GetRegisteredMediaTypes() []string

	// GetRegisteredAttestationSchemes returns a []string of names for
	// schemes that have been registered with the manager by discovered
	// plugins.
	GetRegisteredAttestationSchemes() []string

	// LookupByMediaType returns a handle (implementation of the managed
	// interface) to the plugin that handles the specified mediaType. If
	// the mediaType is not handled by any of the registered plugins, an
	// error is returned.
	LookupByMediaType(mediaType string) (I, error)

	// LookupByName returns a handle (implementation of the managed
	// interface) to the plugin with the specified name. If there is no
	// such plugin, an error is returned.
	LookupByName(name string) (I, error)

	// LookupByScheme returns a handle (implementation of the managed
	// interface) to the plugin that implements the attestation scheme with
	// the specified name. If there is no such plugin, an error is
	// returned.
	LookupByAttestationScheme(name string) (I, error)
}

IManager defines the interface for managing plugins of a particular type (specified by the type parameter).

type IPluggable

type IPluggable interface {
	// GetName returns a string containing the name of the
	// implementation of this IPluggable interface. It is the plugin name.
	GetName() string

	// GetAttestationScheme returns a string containing the name of the
	// attestation scheme handled by this IPluggable implementation.
	GetAttestationScheme() string

	// GetSupportedMediaTypes returns a []string containing the media types
	// this plugin is capable of handling.
	GetSupportedMediaTypes() []string
}

IPluggable respresents a "pluggable" point within Veraison services. It is the common interfaces shared by all Veraison plugins loaded through this framework.

type IPluginContext

type IPluginContext interface {
	GetName() string
	GetAttestationScheme() string
	GetTypeName() string
	GetPath() string
	GetHandle() interface{}
	Close()
}

IPluginContext is the common interace for handling all PluginContext[I] type instances of the generic PluginContext[].

type Plugin

type Plugin[I IPluggable] struct {
	Name string
	Impl I
}

func (*Plugin[I]) Client

func (p *Plugin[I]) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error)

func (*Plugin[I]) Server

func (p *Plugin[I]) Server(*plugin.MuxBroker) (interface{}, error)

type PluginContext

type PluginContext[I IPluggable] struct {
	// Path to the exectable binary containing the plugin implementation
	Path string
	// Name of this plugin
	Name string
	// Name of the attestatin scheme implemented by this plugin
	Scheme string
	// SupportedMediaTypes are the types of input this plugin can process.
	// This is is the method by which a plugin is selected.
	SupportedMediaTypes []string
	// Handle is actual RPC interface to the plugin implementation.
	Handle I
	// contains filtered or unexported fields
}

PluginConntext is a generic for handling Veraison services plugins. It is parameterised on the IPluggale interface it handles.

func (PluginContext[I]) Close

func (o PluginContext[I]) Close()

func (PluginContext[I]) GetAttestationScheme

func (o PluginContext[I]) GetAttestationScheme() string

func (PluginContext[I]) GetHandle

func (o PluginContext[I]) GetHandle() interface{}

func (PluginContext[I]) GetName

func (o PluginContext[I]) GetName() string

func (PluginContext[I]) GetPath

func (o PluginContext[I]) GetPath() string

func (PluginContext[I]) GetTypeName

func (o PluginContext[I]) GetTypeName() string

type RPCChannel

type RPCChannel[I IPluggable] struct {
	GetClient func(c *rpc.Client) interface{}
	GetServer func(i I) interface{}
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL