Merge pull request #1546 from prymitive/anchor-regexes

fix(backend): anchor all regexes in the config
This commit is contained in:
Łukasz Mierzwa
2020-03-26 16:29:33 +00:00
committed by GitHub
7 changed files with 110 additions and 12 deletions
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"github.com/prymitive/karma/internal/alertmanager"
"github.com/prymitive/karma/internal/config"
"github.com/prymitive/karma/internal/models"
"github.com/prymitive/karma/internal/regex"
"github.com/prymitive/karma/internal/slices"
)
@@ -188,7 +189,7 @@ func newSilenceACLFromConfig(cfg config.SilenceACLRule) (*silenceACL, error) {
}
if filter.NameRegex != "" {
re, err := regexp.Compile(filter.NameRegex)
re, err := regex.CompileAnchored(filter.NameRegex)
if err != nil {
return nil, fmt.Errorf("invalid ACL rule, failed to parse name_re %q: %s", filter.NameRegex, err)
}
@@ -196,7 +197,7 @@ func newSilenceACLFromConfig(cfg config.SilenceACLRule) (*silenceACL, error) {
}
if filter.ValueRegex != "" {
re, err := regexp.Compile(filter.ValueRegex)
re, err := regex.CompileAnchored(filter.ValueRegex)
if err != nil {
return nil, fmt.Errorf("invalid ACL rule, failed to parse value_re %q: %s", filter.ValueRegex, err)
}
+3 -3
View File
@@ -9,7 +9,6 @@ import (
"os"
"os/signal"
"path"
"regexp"
"strings"
"syscall"
"time"
@@ -17,6 +16,7 @@ import (
"github.com/prymitive/karma/internal/alertmanager"
"github.com/prymitive/karma/internal/config"
"github.com/prymitive/karma/internal/models"
"github.com/prymitive/karma/internal/regex"
"github.com/prymitive/karma/internal/transform"
"github.com/prymitive/karma/internal/uri"
@@ -80,7 +80,7 @@ func headerAuth(name, valueRegex string) gin.HandlerFunc {
return
}
r := regexp.MustCompile("^" + valueRegex + "$")
r := regex.MustCompileAnchored(valueRegex)
matches := r.FindAllStringSubmatch(user, 1)
if len(matches) > 0 && len(matches[0]) > 1 {
c.Set(gin.AuthUserKey, matches[0][1])
@@ -274,7 +274,7 @@ func mainSetup(errorHandling pflag.ErrorHandling) (*gin.Engine, error) {
if rule.Regex == "" || rule.URITemplate == "" {
return nil, fmt.Errorf("Invalid link detect rule, regex '%s' uriTemplate '%s'", rule.Regex, rule.URITemplate)
}
re, err := regexp.Compile(rule.Regex)
re, err := regex.CompileAnchored(rule.Regex)
if err != nil {
return nil, fmt.Errorf("Invalid link detect rule '%s': %s", rule.Regex, err)
}
+2
View File
@@ -203,9 +203,11 @@ matchers:
Filter works by comparing `name` and `name_re` with silence matcher `name`,
`value` and `value_re` with silence matcher `value` and `isRegex` on the
filter with `isRegex` on silence matcher. See examples below.
All regexes will be automatically anchored.
- `matchers:required` - list of additional matchers that must be part of the
silence if it matches groups, alertmanagers and filters. This is only used
if `action` is set to `requireMatcher`.
All regexes will be automatically anchored.
Syntax for each matcher:
```YAML
+7 -4
View File
@@ -44,7 +44,7 @@ Syntax:
authentication:
header:
name: string
value_re: string
value_re: regex
basicAuth:
users:
- username: string
@@ -59,6 +59,7 @@ authentication:
request header value (when `authentication:users:header:name` is set).
It must include one numbered capturing group, whatever is matched by that
group will be used as the silence form author field.
All regexes are anchored.
This option must be set when `authentication:users:header:name` is set.
- `authentication:users` - list of users (username & password) allowed to login.
Passwords are stored plain without any encryption.
@@ -654,7 +655,7 @@ labels:
custom:
foo:
- value: string
value_re: string
value_re: regex
color: string
keep: list of strings
strip: list of strings
@@ -674,7 +675,8 @@ labels:
- `value` - the exact value of the label to match against
- `value_re` - Go compatible
[regular expression](https://golang.org/pkg/regexp/) to match against
[regular expression](https://golang.org/pkg/regexp/) to match against.
All regexes will be automatically anchored.
- `color`: color to apply if either `value` or `value_re` matches
Either `value` or `value_re` is required, both can be set in which case
@@ -854,7 +856,8 @@ silences:
turn them into links.
Each rule must specify:
- `regex` - regular expression that matches ticket system IDs. Each regex must
contain at least one capture group `(regex)`.
contain at least one capture group `(regex)`. All regexes will be
automatically anchored.
- `uriTemplate` - template string that will be used to generate a link.
Each template must include `$1` which will be replaced with text matched
by the `regex`.
+3 -3
View File
@@ -4,10 +4,10 @@ import (
"bufio"
"bytes"
"os"
"regexp"
"strings"
"time"
"github.com/prymitive/karma/internal/regex"
"github.com/prymitive/karma/internal/slices"
"github.com/prymitive/karma/internal/uri"
@@ -243,7 +243,7 @@ func (config *configSchema) Read(flags *pflag.FlagSet) string {
}
if config.Authentication.Header.ValueRegex != "" {
_, err = regexp.Compile(config.Authentication.Header.ValueRegex)
_, err = regex.CompileAnchored(config.Authentication.Header.ValueRegex)
if err != nil {
log.Fatalf("Invalid regex for authentication.header.value_re: %s", err.Error())
}
@@ -295,7 +295,7 @@ func (config *configSchema) Read(flags *pflag.FlagSet) string {
log.Fatalf("Custom label color for '%s' is missing 'value' or 'value_re'", labelName)
}
if customColor.ValueRegex != "" {
config.Labels.Color.Custom[labelName][i].CompiledRegex, err = regexp.Compile(customColor.ValueRegex)
config.Labels.Color.Custom[labelName][i].CompiledRegex, err = regex.CompileAnchored(customColor.ValueRegex)
if err != nil {
log.Fatalf("Failed to parse custom color regex rule '%s' for '%s' label: %s", customColor.ValueRegex, labelName, err)
}
+26
View File
@@ -0,0 +1,26 @@
package regex
import (
"regexp"
"strings"
)
func wrapRegex(r string) string {
var prefix, suffix string
if !strings.HasPrefix(r, "^") {
prefix = "^"
}
if !strings.HasSuffix(r, "$") {
suffix = "$"
}
return prefix + r + suffix
}
func MustCompileAnchored(r string) *regexp.Regexp {
return regexp.MustCompile(wrapRegex(r))
}
func CompileAnchored(r string) (*regexp.Regexp, error) {
return regexp.Compile(wrapRegex(r))
}
+66
View File
@@ -0,0 +1,66 @@
package regex_test
import (
"fmt"
"testing"
"github.com/prymitive/karma/internal/regex"
)
func TestMustCompileAnchored(t *testing.T) {
type testCaseT struct {
in string
out string
}
testCases := []testCaseT{
{in: "foo", out: "^foo$"},
{in: "^foo", out: "^foo$"},
{in: "foo$", out: "^foo$"},
{in: "^foo$", out: "^foo$"},
{in: "^^foo$", out: "^^foo$"},
{in: "foo$$", out: "^foo$$"},
}
for _, testCase := range testCases {
t.Run(fmt.Sprintf("%q => %q", testCase.in, testCase.out), func(t *testing.T) {
r := regex.MustCompileAnchored(testCase.in)
if r.String() != testCase.out {
t.Errorf("Regex mismatch, expected %q got %q", testCase.out, r.String())
}
})
}
}
func TestCompileAnchored(t *testing.T) {
type testCaseT struct {
in string
out string
error bool
}
testCases := []testCaseT{
{in: "foo", out: "^foo$"},
{in: "^foo", out: "^foo$"},
{in: "foo$", out: "^foo$"},
{in: "^foo$", out: "^foo$"},
{in: "^^foo$", out: "^^foo$"},
{in: "foo$$", out: "^foo$$"},
{in: ".******", out: "", error: true},
}
for _, testCase := range testCases {
t.Run(fmt.Sprintf("%q => %q", testCase.in, testCase.out), func(t *testing.T) {
r, err := regex.CompileAnchored(testCase.in)
hadError := err != nil
if testCase.error != hadError {
t.Errorf("CompileAnchored err=%v, expected error=%v", err, testCase.error)
}
if err == nil {
if r.String() != testCase.out {
t.Errorf("Regex mismatch, expected %q got %q", testCase.out, r.String())
}
}
})
}
}