Skip to content

Commit

Permalink
Cover backward compatibility for start-prefix regexes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tit Petric committed Sep 2, 2024
1 parent e850bdf commit c42c992
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 35 deletions.
25 changes: 17 additions & 8 deletions gateway/mw_granular_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ func (m *GranularAccessMiddleware) ProcessRequest(w http.ResponseWriter, r *http
return nil, http.StatusOK
}

logger := m.Logger().WithField("path", r.URL.Path)
session := ctxGetSession(r)

sessionVersionData, foundAPI := session.AccessRights[m.Spec.APIID]
Expand All @@ -34,20 +33,30 @@ func (m *GranularAccessMiddleware) ProcessRequest(w http.ResponseWriter, r *http
return nil, http.StatusOK
}

urlPath := m.Spec.StripListenPath(r.URL.Path)
urlPaths := []string{
m.Spec.StripListenPath(r.URL.Path),
r.URL.Path,
}

logger := m.Logger().WithField("path", r.URL.Path)

for _, accessSpec := range sessionVersionData.AllowedURLs {
url := accessSpec.URL
match, err := httputil.MatchEndpoint(url, urlPath)
if err != nil {
logger.WithError(err).Errorf("error matching path regex: %q, skipping", url)
continue

var match bool
var err error
for _, urlPath := range urlPaths {
match, err = httputil.MatchEndpoint(url, urlPath)
if err != nil || !match {
logger.WithError(err).Errorf("error matching path regex: %q, skipping", url)
continue
}
break
}

if !match {
if err != nil || !match {
continue
}

logger.WithField("pattern", url).WithField("match", match).Debug("checking allowed url")

// if a path is matched, but isn't matched on method,
Expand Down
73 changes: 46 additions & 27 deletions gateway/mw_granular_access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,37 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
defer g.Close()

api := g.Gw.BuildAndLoadAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/"
spec.Proxy.ListenPath = "/test"
spec.UseKeylessAccess = false
})[0]

allowedURLs := []user.AccessSpec{
{
URL: "/valid_path",
Methods: []string{"GET"},
},
{
URL: "^/test/try_valid_path",
Methods: []string{"GET"},
},
}

_, directKey := g.CreateSession(func(s *user.SessionState) {
s.AccessRights = map[string]user.AccessDefinition{
api.APIID: {
APIID: api.APIID,
APIName: api.Name,
AllowedURLs: []user.AccessSpec{
{
URL: "^/*.$",
Methods: []string{"GET"},
},
{
URL: "^/valid_path.*",
Methods: []string{"GET"},
},
},
APIID: api.APIID,
APIName: api.Name,
AllowedURLs: allowedURLs,
},
}
})

pID := g.CreatePolicy(func(p *user.Policy) {
p.AccessRights = map[string]user.AccessDefinition{
api.APIID: {
APIID: api.APIID,
APIName: api.Name,
AllowedURLs: []user.AccessSpec{
{
URL: "^/valid_path.*",
Methods: []string{"GET"},
},
},
APIID: api.APIID,
APIName: api.Name,
AllowedURLs: allowedURLs,
},
}
})
Expand All @@ -61,10 +58,21 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
header.Authorization: directKey,
}

t.Run("should return 200 OK on regex matching listen path", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/test/try_valid_path",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: authHeaderWithDirectKey,
},
}...)
})

t.Run("should return 200 OK on allowed path with allowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/valid_path",
Path: "/test/valid_path",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: authHeaderWithDirectKey,
Expand All @@ -75,7 +83,7 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
t.Run("should return 403 Forbidden on allowed path with disallowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/valid_path",
Path: "/test/valid_path",
Method: http.MethodPost,
Code: http.StatusForbidden,
Headers: authHeaderWithDirectKey,
Expand All @@ -86,7 +94,7 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
t.Run("should return 403 Forbidden on disallowed path with allowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/invalid_path",
Path: "/test/invalid_path",
Method: http.MethodGet,
Code: http.StatusForbidden,
Headers: authHeaderWithDirectKey,
Expand All @@ -101,10 +109,21 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
header.Authorization: policyAppliedKey,
}

t.Run("should return 200 OK on regex matching listen path", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/test/try_valid_path",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: authHeaderWithPolicyAppliedKey,
},
}...)
})

t.Run("should return 200 OK on allowed path with allowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/valid_path",
Path: "/test/valid_path",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: authHeaderWithPolicyAppliedKey,
Expand All @@ -115,7 +134,7 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
t.Run("should return 403 Forbidden on allowed path with disallowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/valid_path",
Path: "/test/valid_path",
Method: http.MethodPost,
Code: http.StatusForbidden,
Headers: authHeaderWithPolicyAppliedKey,
Expand All @@ -126,7 +145,7 @@ func TestGranularAccessMiddleware_ProcessRequest(t *testing.T) {
t.Run("should return 403 Forbidden on disallowed path with allowed method", func(t *testing.T) {
_, _ = g.Run(t, []test.TestCase{
{
Path: "/invalid_path",
Path: "/test/invalid_path",
Method: http.MethodGet,
Code: http.StatusForbidden,
Headers: authHeaderWithPolicyAppliedKey,
Expand Down

0 comments on commit c42c992

Please sign in to comment.