@@ -13,6 +13,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -21,6 +22,8 @@ import (
|
||||
|
||||
var version = "dev"
|
||||
|
||||
var validRepositoryName = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$`)
|
||||
|
||||
type clientConfig struct {
|
||||
server string
|
||||
token string
|
||||
@@ -81,6 +84,9 @@ func upload(args []string) error {
|
||||
if *policy == "" || *file == "" {
|
||||
return errors.New("-policy and -file are required")
|
||||
}
|
||||
if err := validateRepositoryName("-policy", *policy); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Open(*file)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -135,12 +141,18 @@ func profileSet(args []string) error {
|
||||
if *name == "" || len(policies) == 0 {
|
||||
return errors.New("-name and at least one -policy are required")
|
||||
}
|
||||
if err := validateRepositoryName("-name", *name); err != nil {
|
||||
return err
|
||||
}
|
||||
refs := make([]model.ProfilePolicy, 0, len(policies))
|
||||
for _, value := range policies {
|
||||
policy, ver, ok := strings.Cut(value, "@")
|
||||
if !ok || policy == "" || ver == "" {
|
||||
return fmt.Errorf("invalid policy reference %q; expected name@latest or name@version", value)
|
||||
}
|
||||
if err := validateRepositoryName("policy reference", policy); err != nil {
|
||||
return err
|
||||
}
|
||||
refs = append(refs, model.ProfilePolicy{Policy: policy, Version: ver})
|
||||
}
|
||||
body, _ := json.Marshal(map[string]any{"policies": refs})
|
||||
@@ -172,6 +184,13 @@ func getList(args []string, path string) error {
|
||||
return doAndPrint(cfg, req)
|
||||
}
|
||||
|
||||
func validateRepositoryName(label, value string) error {
|
||||
if !validRepositoryName.MatchString(value) {
|
||||
return fmt.Errorf("invalid %s %q: must match %s (maximum 64 characters; no spaces)", label, value, validRepositoryName.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateClient(server, token string, insecure bool) (clientConfig, error) {
|
||||
if server == "" || token == "" {
|
||||
return clientConfig{}, errors.New("server and token are required")
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestValidateRepositoryName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
ok bool
|
||||
}{
|
||||
{name: "simple", value: "windows-firewall", ok: true},
|
||||
{name: "dots and underscores", value: "MSFT.Server_2022", ok: true},
|
||||
{name: "space", value: "Server Windows Firewall", ok: false},
|
||||
{name: "umlaut", value: "server-härtung", ok: false},
|
||||
{name: "leading hyphen", value: "-server", ok: false},
|
||||
{name: "too long", value: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ok: false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validateRepositoryName("test", tt.value)
|
||||
if tt.ok && err != nil {
|
||||
t.Fatalf("expected valid name, got %v", err)
|
||||
}
|
||||
if !tt.ok && err == nil {
|
||||
t.Fatalf("expected invalid name")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user