Skip to content

Improve plugin interface #259

@Benehiko

Description

@Benehiko

Plugins in the secrets engine were built and tailored around the concept of a Resolver interface which has a singular function to retrieve a secret from a provider based on a pattern.

A request might look as follows:

POST http://localhost/resolver.v1.ResolverService/GetSecret  -H "Content-Type: application/json" -d '{"pattern": "foo"}'

-> http.Handler
-> protobuf handler
-> `engine.regResolver`
-> `engine.regResolver.GetSecrets()`
-> list all registered providers from `engine.regResolver.registry.GetAll()`
-> `engine.runtime.GetSecrets()`
-> resolver service
-> resolver.GetSecret
-> builtin plugin GetSecret 

As shown above, this is a high-level call trace for a built-in plugin. We implement the secrets.Resolver interface in multiple places instead of just for a specific plugin type. We tightly coupled the handler endpoint with the underlying plugin.

A built-in plugin gets defined inside the engine/builtins/<plugin> directory, where they implement the engine.Plugin interface.

https://github.com/docker/secrets-engine/blob/main/engine/adaptation.go#L42-L46

Plugins are created individually inside the daemon func main and passed along to the engine.New function. Here they are eventually managed the wrapBuiltins function.

https://github.com/docker/secrets-engine/blob/main/engine/builtin.go#L114-L122

This translates into a call to newInternalRuntime which accepts the engine.Plugin interface.
https://github.com/docker/secrets-engine/blob/main/engine/builtin.go#L22

The engine.Plugin interface is tightly coupled with the plugin.Resolver interface which is an alias of secrets.Resolver.

This makes it difficult to create a plugin that is not a resolver. Creating plugins that could by of another plugin type would mean adding a new internalRuntime type which implements the runtime interface. The runtime interface also depends upon the secrets.Resolver interface. Which means we would need to simplify the runtime interface and remove the hard dependency upon secrets.Resolver. A more general resolver service is needed to instead of just specifying GetSecrets it needs to be dynamic, based upon the underlying type (i.e. it cannot just accept a secrets.Resolver type).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions