From 44c6bfa5b1dc6bbc6c8db49a4bf63c0101ac10a8 Mon Sep 17 00:00:00 2001 From: Nathan Pierce Date: Wed, 9 Oct 2024 10:08:41 -0500 Subject: [PATCH] Global private key support --- Makefile | 2 +- docker/docker-compose.yml | 14 +++++++++++++- internal/config/config.go | 17 +++++++++++------ main.go | 4 ++++ plugins/handlers/github/github.go | 12 ++++++++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 09a926d..6c409d3 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ go.releaser: git tag -a "$(VERSION)" -m "Version $(VERSION)" echo "LATEST TAG: $$(git describe --tags --abbrev=0)" goreleaser release --verbose --clean - file dist/* | grep executable | awk '{print $1}' | cut -d: -f1 | xargs rm -f + # file dist/* | grep executable | awk '{print $1}' | cut -d: -f1 | xargs rm -f #go.lint: @ Run `golangci-lint run` against the current code go.lint: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index db7268e..ba0a2bb 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -12,7 +12,19 @@ services: - "8081:8081" environment: # - LOG_LEVEL=dev - - ANKLET_CONFIG_FILE_NAME=receiver-config.yml + - ANKLET_CONFIG_FILE_NAME=org-receiver-config.yml + # ANKLET_GLOBAL_PRIVATE_KEY allows you to use the same private key for all runners + # instead of defining a different one in the config.yml file for each runner. + # You can also set it to be the PEM contents, vs pointing to a file. + # - ANKLET_GLOBAL_PRIVATE_KEY=/Users/nathanpierce/veertuinc-anklet.2024-07-19.private-key.pem + # - | + # ANKLET_GLOBAL_PRIVATE_KEY= + # -----BEGIN RSA PRIVATE KEY----- + # MIIEpAIBAAKCAQEAyqZDXOEzV5gRocWAhH73chGjn4HBh1UCG2Du4v9JmcjfyYT3 + # WvszUgAogTWqkSV4H1iL9NKfmKlA1GKngaXFCt5A1IbdR1KTkR0uisiqWO5Bzayr + # U5h+40ht0IjP3v+xQ8BWgjWbhHzPXbhcsmsTQvFfo0vAm+/UcwLKqpp0oUt11AVA + # . . . + # -----END RSA PRIVATE KEY----- # AGGREGATOR ################################################### # - ANKLET_METRICS_AGGREGATOR=true # - ANKLET_METRICS_PORT=8081 diff --git a/internal/config/config.go b/internal/config/config.go index 226b262..437f45b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -15,12 +15,13 @@ import ( type ContextKey string type Config struct { - Plugins []Plugin `yaml:"plugins"` - Log Log `yaml:"log"` - PidFileDir string `yaml:"pid_file_dir"` - LogFileDir string `yaml:"log_file_dir"` - WorkDir string `yaml:"work_dir"` - Metrics Metrics `yaml:"metrics"` + Plugins []Plugin `yaml:"plugins"` + Log Log `yaml:"log"` + PidFileDir string `yaml:"pid_file_dir"` + LogFileDir string `yaml:"log_file_dir"` + WorkDir string `yaml:"work_dir"` + Metrics Metrics `yaml:"metrics"` + GlobalPrivateKey string `yaml:"global_private_key"` } type Log struct { @@ -146,6 +147,10 @@ func LoadInEnvs(config Config) (Config, error) { if workDir != "" { config.WorkDir = workDir } + envGlobalPrivateKey := os.Getenv("ANKLET_GLOBAL_PRIVATE_KEY") + if envGlobalPrivateKey != "" { + config.GlobalPrivateKey = envGlobalPrivateKey + } // pidFileDir := os.Getenv("ANKLET_PID_FILE_DIR") // if pidFileDir != "" { // config.PidFileDir = pidFileDir diff --git a/main.go b/main.go index 2032b58..d340106 100644 --- a/main.go +++ b/main.go @@ -320,6 +320,10 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. pluginCtx = context.WithValue(pluginCtx, config.ContextKey("isRepoSet"), true) } + if plugin.PrivateKey == "" && loadedConfig.GlobalPrivateKey != "" { + plugin.PrivateKey = loadedConfig.GlobalPrivateKey + } + pluginCtx = context.WithValue(pluginCtx, config.ContextKey("plugin"), plugin) pluginCtx = logging.AppendCtx(pluginCtx, slog.String("pluginName", plugin.Name)) pluginCtx = context.WithValue(pluginCtx, config.ContextKey("logger"), logger) diff --git a/plugins/handlers/github/github.go b/plugins/handlers/github/github.go index ff563c6..3fc471d 100644 --- a/plugins/handlers/github/github.go +++ b/plugins/handlers/github/github.go @@ -487,7 +487,7 @@ func Run( logger.InfoContext(pluginCtx, "checking for jobs....") if ctxPlugin.Token == "" && ctxPlugin.PrivateKey == "" { - logging.Panic(workerCtx, pluginCtx, "token and private_key are not set in anklet.yaml:plugins:"+ctxPlugin.Name+":token/private_key") + logging.Panic(workerCtx, pluginCtx, "token or private_key are not set at global level or in anklet.yaml:plugins:"+ctxPlugin.Name+":token/private_key") } if ctxPlugin.PrivateKey != "" && (ctxPlugin.AppID == 0 || ctxPlugin.InstallationID == 0) { logging.Panic(workerCtx, pluginCtx, "private_key, app_id, and installation_id must all be set in anklet.yaml:plugins:"+ctxPlugin.Name+"") @@ -509,7 +509,15 @@ func Run( httpTransport := config.GetHttpTransportFromContext(pluginCtx) var githubClient *github.Client if ctxPlugin.PrivateKey != "" { - itr, err := ghinstallation.NewKeyFromFile(httpTransport, int64(ctxPlugin.AppID), int64(ctxPlugin.InstallationID), ctxPlugin.PrivateKey) + // support private key in a file or as text + var privateKey []byte + privateKeyData, err := os.ReadFile(ctxPlugin.PrivateKey) + if err == nil { + privateKey = privateKeyData + } else { + privateKey = []byte(ctxPlugin.PrivateKey) + } + itr, err := ghinstallation.New(httpTransport, int64(ctxPlugin.AppID), int64(ctxPlugin.InstallationID), privateKey) if err != nil { metricsData.IncrementTotalFailedRunsSinceStart() logger.ErrorContext(pluginCtx, "error creating github app installation token", "err", err)