Skip to content

Commit 5b343c4

Browse files
authored
Added pipeline name validation (#239)
* Added pipeline name validation * Slight fix of the error message * Removed debug comment * Renamed function for better naming * Removed mod addition
1 parent 9b6551b commit 5b343c4

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

handlers/pipeline_test.go

+27-2
Original file line numberDiff line numberDiff line change
@@ -779,8 +779,8 @@ func TestPipelineCheckPeriodicSchedules(t *testing.T) {
779779
})
780780
}
781781

782-
func TestPipelineNameAvailable(t *testing.T) {
783-
tmp, _ := ioutil.TempDir("", "TestPipelineNameAvailable")
782+
func TestPipelineNameValidation(t *testing.T) {
783+
tmp, _ := ioutil.TempDir("", "TestPipelineNameValidation")
784784
dataDir := tmp
785785

786786
gaia.Cfg = &gaia.Config{
@@ -870,6 +870,31 @@ func TestPipelineNameAvailable(t *testing.T) {
870870
}
871871
})
872872

873+
t.Run("fails for pipeline name with invalid character", func(t *testing.T) {
874+
req := httptest.NewRequest(echo.GET, "/", nil)
875+
req.Header.Set("Content-Type", "application/json")
876+
rec := httptest.NewRecorder()
877+
c := e.NewContext(req, rec)
878+
c.SetPath("/api/" + gaia.APIVersion + "/pipeline/name")
879+
q := req.URL.Query()
880+
q.Add("name", "this[]isinvalid;")
881+
req.URL.RawQuery = q.Encode()
882+
883+
_ = PipelineNameAvailable(c)
884+
885+
if rec.Code != http.StatusBadRequest {
886+
t.Fatalf("expected response code %v got %v", http.StatusBadRequest, rec.Code)
887+
}
888+
bodyBytes, err := ioutil.ReadAll(rec.Body)
889+
if err != nil {
890+
t.Fatalf("cannot read response body: %s", err.Error())
891+
}
892+
nameContainsInvalidCharacter := "must match [A-z][0-9][-][_][ ]"
893+
if string(bodyBytes[:]) != nameContainsInvalidCharacter {
894+
t.Fatalf("error message should be '%s' but was '%s'", nameContainsInvalidCharacter, string(bodyBytes[:]))
895+
}
896+
})
897+
873898
t.Run("works for pipeline with different name", func(t *testing.T) {
874899
req := httptest.NewRequest(echo.GET, "/", nil)
875900
req.Header.Set("Content-Type", "application/json")

workers/pipeline/create_pipeline.go

+15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"strings"
7+
"unicode"
78

89
"github.com/gaia-pipeline/gaia/security"
910

@@ -34,6 +35,9 @@ var (
3435

3536
// errPipelineNameInUse is thrown when a pipelines name is already in use
3637
errPipelineNameInUse = errors.New("pipeline name is already in use")
38+
39+
// errPipelineNameInvalid is thrown when the pipeline name contains invalid characters
40+
errPipelineNameInvalid = errors.New("must match [A-z][0-9][-][_][ ]")
3741
)
3842

3943
// CreatePipeline is the main function which executes step by step the creation
@@ -166,6 +170,17 @@ func CreatePipeline(p *gaia.CreatePipeline) {
166170
// ValidatePipelineName validates a given pipeline name and
167171
// returns the correct error back.
168172
func ValidatePipelineName(pName string) error {
173+
174+
valid := func(r rune) bool {
175+
return unicode.IsDigit(r) || unicode.IsLetter(r) || unicode.IsSpace(r) || r == '-' || r == '_'
176+
}
177+
// Note, this is faster than regex.
178+
for _, c := range pName {
179+
if !valid(c) {
180+
return errPipelineNameInvalid
181+
}
182+
}
183+
169184
// The name could contain a path. Split it up.
170185
path := strings.Split(pName, pipelinePathSplitChar)
171186

0 commit comments

Comments
 (0)