1- # Docker Secrets Engine
1+ # Secrets Engine SDK
22
33[ ![ build] ( https://github.com/docker/secrets-engine/actions/workflows/build.yml/badge.svg?branch=main )] ( https://github.com/docker/secrets-engine/actions/workflows/build.yml )
44[ ![ unit tests] ( https://github.com/docker/secrets-engine/actions/workflows/unittests.yml/badge.svg?branch=main )] ( https://github.com/docker/secrets-engine/actions/workflows/unittests.yml )
55[ ![ lint] ( https://github.com/docker/secrets-engine/actions/workflows/lint.yml/badge.svg?branch=main )] ( https://github.com/docker/secrets-engine/actions/workflows/lint.yml )
66[ ![ License] ( https://img.shields.io/badge/license-MIT-blue )] ( https://github.com/docker/secrets-engine/blob/main/LICENSE )
77
8- ## Getting Started
8+ ## Quickstart
99
10- Run a local engine:
10+ Secrets Engine and [ docker pass ] ( https://docs.docker.com/reference/cli/docker/pass/ ) are bundled with [ Docker Desktop ] ( https://docs.docker.com/desktop/ ) .
1111
12- ``` console
13- $ make engine
14- CGO_ENABLED=1 go build -trimpath -ldflags "-s -w" -o ./dist/secrets-engine ./engine/daemon
15- $ ./dist/secrets-engine
16- 2025/08/12 10:20:45 engine: secrets engine starting up... (~/.cache/secrets-engine/engine.sock)
17- 2025/08/12 10:20:45 engine: discovered builtin plugin: pass
18- 2025/08/12 10:20:45 engine: registering plugin 'pass'...
19- 2025/08/12 10:20:45 engine: plugin priority order
20- 2025/08/12 10:20:45 engine: #1: pass
21- 2025/08/12 10:20:45 engine: secrets engine ready
22- ```
23-
24- Create secrets in your keychain:
25-
26- ``` console
27- $ make pass
28- CGO_ENABLED=1 go build -trimpath -ldflags "-s -w" -o ./dist/docker-pass ./pass
29- $ ./dist/docker-pass set foo=bar
30- $ ./dist/docker-pass set baz=something
31- $ ./dist/docker-pass ls
32- baz
33- foo
34- ```
35-
36- Query secrets from the engine:
12+ Let's store a secret using ` docker pass ` in the OS Keychain and then inject it
13+ into a running container using Secrets Engine.
3714
3815``` console
39- $ curl --unix-socket ~ /.cache/secrets-engine/engine.sock \
40- -X POST http://localhost/resolver.v1.ResolverService/GetSecrets \
41- -H "Content-Type: application/json" -d '{"pattern": "foo"}'
42- {"id":"foo","value":"bar","provider":"docker-pass","version":"","error":"","createdAt":"0001-01-01T00:00:00Z","resolvedAt":"2025-08-12T08:25:06.166714Z","expiresAt":"0001-01-01T00:00:00Z"}
16+ # Store ` Foo` in the OS Keychain
17+ $ docker pass set Foo=bar
18+ # Tell docker to use the Secrets Engine using the ` se://` URI on an environment variable
19+ $ docker run --rm -e Foo=se://Foo busybox /bin/sh -c " echo \$ {Foo}"
20+ $ bar
4321```
4422
45- > [ !NOTE]
46- > On linux the socket might be on /run/user/1000/secrets-engine/engine.sock
47-
48- ## Integration
49-
50- There are three ways to integrate with the secrets engine:
23+ # Developer Guides
5124
52- - Client integrator: Use the client to query secrets and to build business logic on top that makes use of the engine.
53- - Plugin author: Create plugins for an engine.
54- - Engine integrator: Build/run an engine yourself.
55-
56- ### Using the client
25+ ## How to query secrets
5726
5827Use the ` client ` module in your project:
5928
@@ -77,7 +46,9 @@ if err != nil {
7746fmt.Println (resp.Value )
7847```
7948
80- ### Writing your own Plugin
49+ ## How to create a plugin
50+
51+ ### 1. Implement the plugin interface
8152
8253Use the ` plugin ` module in your project:
8354
@@ -95,19 +66,21 @@ type myPlugin struct {
9566 secrets map [secrets.ID ]string
9667}
9768
98- func (p *myPlugin ) GetSecret (_ context .Context , request secrets .Request ) (secrets .Envelope , error ) {
69+ func (p *myPlugin ) GetSecret (_ context .Context , request secrets .Request ) ([] secrets .Envelope , error ) {
9970 p.m .Lock ()
10071 defer p.m .Unlock ()
72+
73+ var result []secrets.Envelope
10174 for id , value := range p.secrets {
102- if request.ID == id {
103- return secrets.Envelope {
75+ if request.Pattern . Match (id) {
76+ result = append (result, secrets.Envelope {
10477 ID: id,
10578 Value: []byte (value),
10679 CreatedAt: time.Now (),
107- }, nil
80+ })
10881 }
10982 }
110- return secrets. EnvelopeErr (request, secrets. ErrNotFound ), secrets. ErrNotFound
83+ return result, nil
11184}
11285
11386func (p *myPlugin ) Config () plugin .Config {
@@ -118,7 +91,9 @@ func (p *myPlugin) Config() plugin.Config {
11891}
11992```
12093
121- Create your plugin binary:
94+ ### 2. Build a plugin binary
95+
96+ Create a Go binary that use your plugin interface implementation and runs it through the plugin SDK:
12297
12398``` go
12499package main
@@ -141,6 +116,17 @@ func main() {
141116}
142117```
143118
144- ### Running the Engine
119+ ### 3. Test and verify the plugin:
120+
121+ The secrets engine is integrated with Docker Desktop.
122+ To verify your plugin works, run the binary.
123+ Using the SDK it will automatically connect to the secrets engine in Docker Desktop.
124+ Then, you can query secrets, e.g. using curl:
125+
126+ ``` console
127+ $ curl --unix-socket ~ /Library/Caches/docker-secrets-engine/engine.sock \
128+ -X POST http://localhost/resolver.v1.ResolverService/GetSecrets \
129+ -H "Content-Type: application/json" -d '{"pattern": "foo"}'
130+ {"id":"foo","value":"bar","provider":"docker-pass","version":"","error":"","createdAt":"0001-01-01T00:00:00Z","resolvedAt":"2025-08-12T08:25:06.166714Z","expiresAt":"0001-01-01T00:00:00Z"}
131+ ```
145132
146- TODO
0 commit comments