From 42203d301a4e60fee118a059d35e929de762976a Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Tue, 21 Jan 2020 16:55:21 +0100 Subject: [PATCH 1/2] chore(issue-213): Validate push prefix format --- api/v1/v1.go | 33 ++++++++++++++++++++++++++++++++- api/v1/v1_test.go | 8 ++++++++ main.go | 7 ++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/api/v1/v1.go b/api/v1/v1.go index 5bef0ce..62cd8db 100644 --- a/api/v1/v1.go +++ b/api/v1/v1.go @@ -10,6 +10,7 @@ import ( "fmt" "html/template" "io" + "regexp" "runtime" "strings" "time" @@ -235,6 +236,26 @@ func getPushPrefix(prefix, defaultPrefix string) string { return prefix } +func validatePushPrefix(prefix string) error { + const ex = `^/[a-z0-9_][a-z0-9_\-\.\/]+/$` + + if prefix == "/" { + return nil + } + + matched, err := regexp.MatchString(ex, prefix) + + if err != nil { + return err + } + + if !matched { + return fmt.Errorf("Push prefix \"%s\" does not match valid pattern: %s", prefix, ex) + } + + return nil +} + // CollectPushTags blends passed collection with information fetched from [local] "push" registry, // makes required comparisons between them and spits organized info back as collection.Collection func (api *API) CollectPushTags(cn *collection.Collection, push PushConfig) (*collection.Collection, error) { @@ -257,7 +278,13 @@ func (api *API) CollectPushTags(cn *collection.Collection, push PushConfig) (*co go func(repo *repository.Repository, i int, done chan error) { refs[i] = repo.Ref() - pushPath, perr := pushPathTemplate(getPushPrefix(push.Prefix, repo.PushPrefix()), repo.PushPath(push.PathSeparator), repo.Name()) + pushPrefix := getPushPrefix(push.Prefix, repo.PushPrefix()) + if err := validatePushPrefix(pushPrefix); err != nil { + done <- err + return + } + + pushPath, perr := pushPathTemplate(pushPrefix, repo.PushPath(push.PathSeparator), repo.Name()) if perr != nil { done <- perr return @@ -439,6 +466,10 @@ func (api *API) PushTags(cn *collection.Collection, push PushConfig) error { for _, tg := range tags { srcRef := repo.Name() + ":" + tg.Name() pushPrefix := getPushPrefix(push.Prefix, repo.PushPrefix()) + if err := validatePushPrefix(pushPrefix); err != nil { + done <- err + return + } pushPath := repo.PushPath(push.PathSeparator) fullPath, perr := pushPathTemplate(pushPrefix, pushPath, repo.Name()) if perr != nil { diff --git a/api/v1/v1_test.go b/api/v1/v1_test.go index df7a0c3..f49f703 100644 --- a/api/v1/v1_test.go +++ b/api/v1/v1_test.go @@ -288,3 +288,11 @@ func TestMakePushTagTemplate(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "SNAPSHOT-16.3.1-"+curDate, actualDate) } + +func TestValidatePushPrefix(t *testing.T) { + assert.NoError(t, validatePushPrefix("/")) + assert.NoError(t, validatePushPrefix("/foo/bar/")) + + assert.Error(t, validatePushPrefix("/baz")) + assert.Error(t, validatePushPrefix("http://localhost:5000")) +} diff --git a/main.go b/main.go index 6b63290..75ae8d0 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "time" "github.com/jessevdk/go-flags" + log "github.com/sirupsen/logrus" v1 "github.com/ivanilves/lstags/api/v1" "github.com/ivanilves/lstags/config" @@ -49,10 +50,10 @@ var exitCode = 0 var doNotFail = false func suicide(err error, critical bool) { - fmt.Printf("%s\n", err.Error()) - if !doNotFail || critical { - os.Exit(1) + log.Fatal(err.Error()) + } else { + log.Error(err.Error()) } exitCode = 254 // not typical error code, for "git grep" friendliness From 29726ba2b29def5051e43827e68503c1050a6498 Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Tue, 21 Jan 2020 17:59:55 +0100 Subject: [PATCH 2/2] fix(issue-215): more strict locking (to see where it does break) --- api/v1/registry/client/cache/cache.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/api/v1/registry/client/cache/cache.go b/api/v1/registry/client/cache/cache.go index 01442a9..00ca3c2 100644 --- a/api/v1/registry/client/cache/cache.go +++ b/api/v1/registry/client/cache/cache.go @@ -29,7 +29,7 @@ func (t *token) Exists(key string) bool { _, defined := t.items[key] if !defined && WaitBetween != 0 { - log.Debugf("Locking token operations for %v (key: %s)", WaitBetween, key) + log.Debugf("[EXISTS] Locking token operations for %v (key: %s)", WaitBetween, key) time.Sleep(WaitBetween) } @@ -38,6 +38,14 @@ func (t *token) Exists(key string) bool { // Get gets token for a passed key func (t *token) Get(key string) auth.Token { + t.mux.Lock() + defer t.mux.Unlock() + + if WaitBetween != 0 { + log.Debugf("[GET] Locking token operations for %v (key: %s)", WaitBetween, key) + time.Sleep(WaitBetween) + } + return t.items[key] }