Skip to content

Commit

Permalink
Global private key support
Browse files Browse the repository at this point in the history
  • Loading branch information
NorseGaud committed Oct 9, 2024
1 parent 0f38cd3 commit f16d63e
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 23 deletions.
1 change: 0 additions & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,3 @@ release:
# disable: true
changelog:
disable: true

11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,13 @@ go.build:
chmod +x dist/$(BIN)_v$(VERSION)_$(OS_TYPE)_$(ARCH)

build-linux:
GOOS=linux OS_TYPE=linux $(MAKE) go.build
GOOS=linux OS_TYPE=linux $(MAKE) go.build

run-docker-compose:
cp dist/anklet_v$(VERSION)*_linux_$(ARCH).zip docker/
cd docker && \
rm -f anklet_linux_$(ARCH) && \
unzip anklet_v$(VERSION)*_linux_$(ARCH).zip && \
mv anklet_v$(VERSION)*_linux_$(ARCH) anklet_linux_$(ARCH) && \
rm -f anklet_v$(VERSION)*_linux_$(ARCH).zip && \
docker-compose up --build --force-recreate
15 changes: 13 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,19 @@ services:
- "8081:8081"
environment:
# - LOG_LEVEL=dev
- ANKLET_CONFIG_FILE_NAME=receiver-config.yml
# AGGREGATOR ###################################################
- 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
# . . .
# -----END RSA PRIVATE KEY-----
################################################################
# AGGREGATOR
# - ANKLET_METRICS_AGGREGATOR=true
# - ANKLET_METRICS_PORT=8081
# - ANKLET_METRICS_URLS=http://host.docker.internal:8080/metrics # comma separation for multiple urls
Expand Down
25 changes: 19 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -202,3 +207,11 @@ func GetIsRepoSetFromContext(ctx context.Context) bool {
}
return isRepoSet
}

func GetConfigFileNameFromContext(ctx context.Context) string {
configFileName, ok := ctx.Value(ContextKey("configFileName")).(string)
if !ok {
panic("GetConfigFileNameFromContext failed")
}
return configFileName
}
23 changes: 15 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ func main() {
if err != nil {
panic(err)
}

var configPath string
var configFileName string
if *configFlag != "" {
configPath = *configFlag
} else {
var configFileName string
envConfigFileName := os.Getenv("ANKLET_CONFIG_FILE_NAME")
if envConfigFileName != "" {
configFileName = envConfigFileName
Expand All @@ -84,6 +85,7 @@ func main() {
}
configPath = filepath.Join(homeDir, ".config", "anklet", configFileName)
}
parentCtx = context.WithValue(parentCtx, config.ContextKey("configFileName"), configFileName)

// obtain config
loadedConfig, err := config.LoadConfig(configPath)
Expand Down Expand Up @@ -320,19 +322,24 @@ 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)

ankaCLI, err := anka.NewCLI(pluginCtx)
if err != nil {
pluginCancel()
logger.ErrorContext(pluginCtx, "unable to create anka cli", "error", err)
return
if !strings.Contains(plugin.Plugin, "_receiver") {
ankaCLI, err := anka.NewCLI(pluginCtx)
if err != nil {
pluginCancel()
logger.ErrorContext(pluginCtx, "unable to create anka cli", "error", err)
return
}
pluginCtx = context.WithValue(pluginCtx, config.ContextKey("ankacli"), ankaCLI)
}

pluginCtx = context.WithValue(pluginCtx, config.ContextKey("ankacli"), ankaCLI)

if plugin.Database.Enabled {
databaseClient, err := database.NewClient(pluginCtx, plugin.Database)
if err != nil {
Expand Down
18 changes: 14 additions & 4 deletions plugins/handlers/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,14 +486,16 @@ func Run(

logger.InfoContext(pluginCtx, "checking for jobs....")

configFileName := config.GetConfigFileNameFromContext(pluginCtx)

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 "+configFileName+":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+"")
logging.Panic(workerCtx, pluginCtx, "private_key, app_id, and installation_id must all be set in "+configFileName+":plugins:"+ctxPlugin.Name+"<token/private_key>")
}
if ctxPlugin.Owner == "" {
logging.Panic(workerCtx, pluginCtx, "owner is not set in anklet.yaml:plugins:"+ctxPlugin.Name+":owner")
logging.Panic(workerCtx, pluginCtx, "owner is not set in "+configFileName+":plugins:"+ctxPlugin.Name+"<owner>")
}
// if ctxPlugin.Repo == "" {
// logging.Panic(workerCtx, pluginCtx, "repo is not set in anklet.yaml:plugins:"+ctxPlugin.Name+":repo")
Expand All @@ -509,7 +511,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)
Expand Down
17 changes: 16 additions & 1 deletion plugins/receivers/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log/slog"
"net/http"
"os"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -135,6 +136,12 @@ func Run(
StatusSince: time.Now(),
},
)

if ctxPlugin.Token == "" && ctxPlugin.PrivateKey == "" {
configFileName := config.GetConfigFileNameFromContext(pluginCtx)
logging.Panic(workerCtx, pluginCtx, "token or private_key are not set at global level or in "+configFileName+":plugins:"+ctxPlugin.Name+"<token/private_key>")
}

databaseContainer, err := database.GetDatabaseFromContext(pluginCtx)
if err != nil {
logger.ErrorContext(pluginCtx, "error getting database client from context", "error", err)
Expand All @@ -144,7 +151,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 {
logger.ErrorContext(pluginCtx, "error creating github app installation token", "err", err)
return
Expand Down

0 comments on commit f16d63e

Please sign in to comment.