File size: 2,432 Bytes
1f10f31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package labels

import (
	"errors"
	"net/http"
	"regexp"

	api "github.com/openmeterio/openmeter/api/v3"
	"github.com/openmeterio/openmeter/pkg/framework/commonhttp"
	"github.com/openmeterio/openmeter/pkg/models"
)

// https://regex101.com/?regex=%5E%28%3F%3A%5Ba-zA-Z0-9%5D%28%3F%3A%5Ba-zA-Z0-9._-%5D%5Ba-zA-Z0-9%5D%29%3F%29%7B1%2C63%7D%24&testString=openmeter_good%0Aopenmeter.good%0Aopenmeter-good%0Aopenmeter_bad_%0Aopenmeter-bad-%0Aopenmeter.bad.%0A_openmeter-bad%0A-openmeter-bad%0A.openmeter.bad%0A.openmeter.way_toooooooooooooooooooooooooooooooooooooooooooooooooooooo_long&flags=gm&flavor=pcre2&delimiter=%2F
var keyValueFormat = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9._-]?[a-zA-Z0-9])?){1,63}$`)

// https://regex101.com/?regex=%5E%28%3F%3A%5Ba-zA-Z0-9%5D%28%3F%3A%5Ba-zA-Z0-9._-%5D%5Ba-zA-Z0-9%5D%29%3F%29%7B1%2C63%7D%24&testString=openmeter_good%0Aopenmeter.good%0Aopenmeter-good%0Aopenmeter_bad_%0Aopenmeter-bad-%0Aopenmeter.bad.%0A_openmeter-bad%0A-openmeter-bad%0A.openmeter.bad%0A.openmeter.way_toooooooooooooooooooooooooooooooooooooooooooooooooooooo_long&flags=gm&flavor=pcre2&delimiter=%2F
var reservedPrefixMatcher = regexp.MustCompile(`^(_|kong|konnect|insomnia|mesh|kic|kuma|openmeter)`)

func ValidateLabel(k, v string) error {
	var errs []error

	if !keyValueFormat.MatchString(k) {
		errs = append(errs, models.NewValidationIssue(
			"invalid_label_key_format",
			"label key must be in valid format",
			models.WithFieldString("labels"),
			models.WithCriticalSeverity(),
			commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest),
		))
	}

	if !keyValueFormat.MatchString(v) {
		errs = append(errs, models.NewValidationIssue(
			"invalid_label_value_format",
			"label value must be in valid format",
			models.WithFieldString("labels"),
			models.WithCriticalSeverity(),
			commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest),
		))
	}

	if reservedPrefixMatcher.MatchString(k) {
		errs = append(errs, models.NewValidationIssue(
			"invalid_label_key_prefix",
			"label key must not have reserved prefix",
			models.WithFieldString("labels"),
			models.WithCriticalSeverity(),
			commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest),
		))
	}

	return errors.Join(errs...)
}

func ValidateLabels(l api.Labels) error {
	var errs []error

	for k, v := range l {
		if err := ValidateLabel(k, v); err != nil {
			errs = append(errs, err)
		}
	}

	return errors.Join(errs...)
}