Skip to content

Commit

Permalink
implement singleton registry that knows about all helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
malt3 committed Feb 22, 2025
1 parent 34169c3 commit b7c8d19
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 40 deletions.
4 changes: 2 additions & 2 deletions bzl/private/source_files/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
release_files = [
"//:all_files",
"//agent:all_files",
"//agent/locate:all_files",
"//agent/internal:all_files",
"//agent/internal/lockfile:all_files",
"//agent/locate:all_files",
"//api:all_files",
"//authenticate/gcs:all_files",
"//authenticate/github:all_files",
Expand All @@ -28,9 +28,9 @@ release_files = [
"//config:all_files",
"//helperfactory:all_files",
"//helperfactory/fallback:all_files",
"//helperfactory/string:all_files",
"//installer:all_files",
"//logging:all_files",
"//registry:all_files",
]

dev_files = [
Expand Down
2 changes: 1 addition & 1 deletion config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ go_library(
deps = [
"//agent/locate",
"//api",
"//helperfactory/string",
"//logging",
"//registry",
],
)

Expand Down
6 changes: 3 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

"github.com/tweag/credential-helper/agent/locate"
"github.com/tweag/credential-helper/api"
helperstringfactory "github.com/tweag/credential-helper/helperfactory/string"
"github.com/tweag/credential-helper/logging"
"github.com/tweag/credential-helper/registry"
)

var ErrConfigNotFound = errors.New("config file not found")
Expand Down Expand Up @@ -53,7 +53,7 @@ func (c Config) FindHelper(uri string) (api.Helper, []byte, error) {
if len(urlConfig.Path) > 0 && !globMatch(urlConfig.Path, requested.Path) {
continue
}
helper := helperstringfactory.HelperFromString(urlConfig.Helper)
helper := registry.HelperFromString(urlConfig.Helper)
if helper != nil {
logging.Debugf("selected helper %s from config", urlConfig.Helper)
return helper, urlConfig.Config, nil
Expand All @@ -62,7 +62,7 @@ func (c Config) FindHelper(uri string) (api.Helper, []byte, error) {
}
// this is equivalent to null.Null{}
// but avoids the import of the null package
return helperstringfactory.HelperFromString("null"), nil, nil
return registry.HelperFromString("null"), nil, nil
}

type ConfigReader interface {
Expand Down
11 changes: 11 additions & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ You can find the built-in default implementations under [/authenticate][authenti

The credential helper supports multiple authentication providers in a single helper binary. The factory function determines which `api.Helper` to use based on the request URI. You can find the default implementation in [github.com/tweag/credential-helper/helperfactory/fallback.FallbackHelperFactory][fallback-helper-factory].

## Registering your helper

Custom helpers need to be registered at program startup to work and be recognized correctly. For this, the `registry.Register` function can be called to add a globally known register (with a unique name) to the registry.
Simply add an `init` function to the package that implements `api.Helper`:

```go
func init() {
registry.Register("foo", FooHelper{})
}
```

## (Optional) Replace the default in-memory cache

By default, the agent process uses a simple in-memory key-value store to cache credentials. You can provide a custom implementation to persist credentials (on disk, in a database, in a shared key-value store, using a (hardware backed) secure storage, etc.), implement more selective caching (decide what to keep), or perform other custom logic.
Expand Down
5 changes: 4 additions & 1 deletion examples/customized/helper/authenticate/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ go_library(
srcs = ["pathtoheader.go"],
importpath = "github.com/tweag/credential-helper/examples/customized/helper/authenticate",
visibility = ["//visibility:public"],
deps = ["@tweag-credential-helper//api"],
deps = [
"@tweag-credential-helper//api",
"@tweag-credential-helper//registry",
],
)
8 changes: 8 additions & 0 deletions examples/customized/helper/authenticate/pathtoheader.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ import (
"time"

"github.com/tweag/credential-helper/api"
"github.com/tweag/credential-helper/registry"
)

func init() {
// This code runs when the program starts.
// It registers this helper with the registry under the name `pathtoheader`.
// The registry is used by the agent to look up helpers by name.
registry.Register("pathtoheader", PathToHeader{})
}

// PathToHeader is a credential helper that
// takes a request path and returns
// a custom header including it.
Expand Down
30 changes: 0 additions & 30 deletions helperfactory/string/helperstring.go

This file was deleted.

6 changes: 3 additions & 3 deletions helperfactory/string/BUILD.bazel → registry/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "string",
srcs = ["helperstring.go"],
importpath = "github.com/tweag/credential-helper/helperfactory/string",
name = "registry",
srcs = ["registry.go"],
importpath = "github.com/tweag/credential-helper/registry",
visibility = ["//visibility:public"],
deps = [
"//api",
Expand Down
53 changes: 53 additions & 0 deletions registry/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package registry

import (
"github.com/tweag/credential-helper/api"
authenticateGCS "github.com/tweag/credential-helper/authenticate/gcs"
authenticateGitHub "github.com/tweag/credential-helper/authenticate/github"
authenticateNull "github.com/tweag/credential-helper/authenticate/null"
authenticateOCI "github.com/tweag/credential-helper/authenticate/oci"
authenticateRemoteAPIs "github.com/tweag/credential-helper/authenticate/remoteapis"
authenticateS3 "github.com/tweag/credential-helper/authenticate/s3"
)

var singleton = Helpers{
Map: map[string]api.Helper{
"gcs": &authenticateGCS.GCS{},
"github": &authenticateGitHub.GitHub{},
"null": &authenticateNull.Null{},
"oci": authenticateOCI.NewFallbackOCI(),
"remoteapis": &authenticateRemoteAPIs.RemoteAPIs{},
"s3": &authenticateS3.S3{},
},
}

// HelperFromString returns the helper corresponding to the given string.
func HelperFromString(s string) api.Helper {
return singleton.Map[s]
}

// Register registers a new helper with the given name.
func Register(name string, helper api.Helper) {
singleton.register(name, helper)
}

// Names returns the names of all registered helpers.
func Names() []string {
return singleton.names()
}

type Helpers struct {
Map map[string]api.Helper
}

func (h *Helpers) register(name string, helper api.Helper) {
h.Map[name] = helper
}

func (h *Helpers) names() []string {
names := make([]string, 0, len(h.Map))
for name := range h.Map {
names = append(names, name)
}
return names
}

0 comments on commit b7c8d19

Please sign in to comment.