-
Notifications
You must be signed in to change notification settings - Fork 0
Description
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).