Skip to content

Commit

Permalink
Address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
bergundy committed Nov 13, 2024
1 parent fa5c6e5 commit f5bf8c3
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 35 deletions.
2 changes: 1 addition & 1 deletion common/dynamicconfig/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ is currently processing a task.
// keys for frontend
FrontendHTTPAllowedHosts = NewGlobalTypedSetting(
"frontend.httpAllowedHosts",
[]string{"*"},
[]string(nil),
`HTTP API Requests with a "Host" header matching the allowed hosts will be processed, otherwise rejected.
Wildcards (*) are expanded to allow any substring. By default any Host header is allowed.`,
)
Expand Down
46 changes: 14 additions & 32 deletions common/util/wildcard.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,52 +28,34 @@ import (
"strings"
)

func wildCardStringToRegexpString(pattern string) (string, error) {
if pattern == "" {
return "", errors.New("pattern cannot be empty")
}
var result strings.Builder
result.WriteString("^")
for i, literal := range strings.Split(pattern, "*") {
if i > 0 {
// Replace * with .*
result.WriteString(".*")
}
result.WriteString(regexp.QuoteMeta(literal))
}
result.WriteString("$")
return result.String(), nil
}

// WildCardStringToRegexp converts a given string pattern to a regular expression matching wildcards (*) with any
// substring.
func WildCardStringToRegexp(pattern string) (*regexp.Regexp, error) {
s, err := wildCardStringToRegexpString(pattern)
if err != nil {
return nil, err
if pattern == "" {
return nil, errors.New("pattern cannot be empty")
}
return regexp.Compile(s)
return WildCardStringsToRegexp([]string{pattern})
}

// WildCardStringToRegexps converts a given slices of string patterns to a slice of regular expressions matching
// wildcards (*) with any substring.
func WildCardStringsToRegexp(patterns []string) (*regexp.Regexp, error) {
var result strings.Builder
var errs []error

result.WriteRune('^')
for i, pattern := range patterns {
s, err := wildCardStringToRegexpString(pattern)
if err != nil {
errs = append(errs, err)
continue
result.WriteRune('(')
for i, literal := range strings.Split(pattern, "*") {
if i > 0 {
// Replace * with .*
result.WriteString(".*")
}
result.WriteString(regexp.QuoteMeta(literal))
}
result.WriteString(s)
if i < len(pattern)-1 {
result.WriteRune(')')
if i < len(patterns)-1 {
result.WriteRune('|')
}
}
if len(errs) > 0 {
return nil, errors.Join(errs...)
}
result.WriteRune('$')
return regexp.Compile(result.String())
}
56 changes: 56 additions & 0 deletions common/util/wildcard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// The MIT License
//
// Copyright (c) 2024 Temporal Technologies Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package util_test

import (
"testing"

"github.com/stretchr/testify/require"
"go.temporal.io/server/common/util"
)

func TestWildCardStringToRegexp(t *testing.T) {
re, err := util.WildCardStringToRegexp("a*z")
require.NoError(t, err)
require.Regexp(t, re, "az")
require.Regexp(t, re, "abz")
require.NotRegexp(t, re, "ab")

_, err = util.WildCardStringToRegexp("")
require.ErrorContains(t, err, "pattern cannot be empty")
}

func TestWildCardStringsToRegexp(t *testing.T) {
re, err := util.WildCardStringsToRegexp([]string{"a*z", "b*d"})
require.NoError(t, err)
require.Regexp(t, re, "az")
require.Regexp(t, re, "abz")
require.NotRegexp(t, re, "ab")
require.Regexp(t, re, "bd")
require.Regexp(t, re, "bcd")
require.NotRegexp(t, re, "bc")

re, err = util.WildCardStringsToRegexp([]string{})
require.NoError(t, err)
require.NotRegexp(t, re, "a")
}
2 changes: 1 addition & 1 deletion service/frontend/http_api_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func (h *HTTPAPIServer) serveHTTP(w http.ResponseWriter, r *http.Request) {
func (h *HTTPAPIServer) allowedHostsMiddleware(hf runtime.HandlerFunc) runtime.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
allowedHosts := h.allowedHosts.Get()
if allowedHost.MatchString(r.Host) {
if allowedHosts.MatchString(r.Host) {
hf(w, r, pathParams)
return
}
Expand Down
9 changes: 8 additions & 1 deletion service/frontend/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import (
"google.golang.org/grpc/reflection"
)

var matchAny = regexp.MustCompile(".*")

// Config represents configuration for frontend service
type Config struct {
NumHistoryShards int32
Expand Down Expand Up @@ -335,7 +337,12 @@ func NewConfig(
EnableEagerWorkflowStart: dynamicconfig.EnableEagerWorkflowStart.Get(dc),
ActivityAPIsEnabled: dynamicconfig.ActivityAPIsEnabled.Get(dc),

HTTPAllowedHosts: dynamicconfig.NewGlobalCachedTypedValue(dc, dynamicconfig.FrontendHTTPAllowedHosts, util.WildCardStringsToRegexp),
HTTPAllowedHosts: dynamicconfig.NewGlobalCachedTypedValue(dc, dynamicconfig.FrontendHTTPAllowedHosts, func(patterns []string) (*regexp.Regexp, error) {
if len(patterns) == 0 {
return matchAny, nil
}
return util.WildCardStringsToRegexp(patterns)
}),
}
}

Expand Down

0 comments on commit f5bf8c3

Please sign in to comment.