docker / docker/secrets-engine

Improve plugin interface

Open
#259 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
91
Forks
16
Avg merge
9h 3m
Merged PRs (30d)
24

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).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with engine/adaptation.go, engine/builtin.go, and the daemon's main function to trace plugin creation through engine.New, wrapBuiltins, and newInternalRuntime. Read the runtime, engine.Plugin, and plugin.Resolver interfaces and map their dependencies on secrets.Resolver. Done means the design supports plugin types beyond resolvers without coupling the runtime to secrets.Resolver.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.