Repository: avenga/couper
Pull request #211 (2021-04-15 08:38:51)

Fix: Protected API paths responses with 401 instead of 404

malud: Fixup for #174 

Patch:
diff --git a/config/configload/load.go b/config/configload/load.go
index 018fb54d..019d8cc4 100644
--- a/config/configload/load.go
+++ b/config/configload/load.go
@@ -265,6 +265,18 @@ func refineEndpoints(definedBackends Backends, endpoints config.Endpoints) error
 			return err
 		}
 
+		if endpoint.Pattern == "" {
+			var r hcl.Range
+			if endpoint.Remain != nil {
+				r = endpoint.Remain.MissingItemRange()
+			}
+			return hcl.Diagnostics{&hcl.Diagnostic{
+				Severity: hcl.DiagError,
+				Summary:  "endpoint: missing path pattern",
+				Subject:  &r,
+			}}
+		}
+
 		endpointContent := bodyToContent(endpoint.Remain)
 
 		proxies := endpointContent.Blocks.OfType(proxy)
@@ -523,7 +535,8 @@ func createCatchAllEndpoint() *config.Endpoint {
 	})
 
 	return &config.Endpoint{
-		Remain: hclbody.New(&hcl.BodyContent{}),
+		Pattern: "/**",
+		Remain:  hclbody.New(&hcl.BodyContent{}),
 		Response: &config.Response{
 			Remain: responseBody,
 		},
diff --git a/config/configload/validate.go b/config/configload/validate.go
index ddeb7a14..d4a61120 100644
--- a/config/configload/validate.go
+++ b/config/configload/validate.go
@@ -11,6 +11,10 @@ import (
 )
 
 func uniqueAttributeKey(body hcl.Body) error {
+	if body == nil {
+		return nil
+	}
+
 	content, _, diags := body.PartialContent(meta.AttributesSchema)
 	if diags.HasErrors() {
 		return diags
diff --git a/config/runtime/server.go b/config/runtime/server.go
index d5b513ff..625865e3 100644
--- a/config/runtime/server.go
+++ b/config/runtime/server.go
@@ -210,6 +210,10 @@ func NewServerConfiguration(
 			var corsOptions *middleware.CORSOptions
 			var errTpl *errors.Template
 
+			if endpointConf.Pattern == "" { // could happen for internally registered endpoints
+				return nil, fmt.Errorf("endpoint path pattern required")
+			}
+
 			if endpointConf.ErrorFile != "" {
 				errTpl, err = errors.NewTemplateFromFile(endpointConf.ErrorFile, log)
 				if err != nil {
@@ -559,8 +563,7 @@ func configureAccessControls(conf *config.Couper, confCtx *hcl.EvalContext) (ac.
 
 func configureProtectedHandler(m ac.Map, errTpl *errors.Template, parentAC, handlerAC config.AccessControl, h http.Handler) http.Handler {
 	var acList ac.List
-	for _, acName := range parentAC.
-		Merge(handlerAC).List() {
+	for _, acName := range parentAC.Merge(handlerAC).List() {
 		m.MustExist(acName)
 		acList = append(acList, ac.ListItem{Func: m[acName], Name: acName})
 	}


Test patch:
diff --git a/config/configload/load_test.go b/config/configload/load_test.go
new file mode 100644
index 00000000..655ba9fc
--- /dev/null
+++ b/config/configload/load_test.go
@@ -0,0 +1,15 @@
+package configload
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/avenga/couper/config"
+)
+
+func Test_refineEndpoints_noPattern(t *testing.T) {
+	err := refineEndpoints(nil, config.Endpoints{{Pattern: ""}})
+	if err == nil || !strings.HasSuffix(err.Error(), "endpoint: missing path pattern; ") {
+		t.Errorf("refineEndpoints() error = %v, wantErr: endpoint: missing path pattern ", err)
+	}
+}
diff --git a/server/http_integration_test.go b/server/http_integration_test.go
index 1ceb0089..f2ea9da6 100644
--- a/server/http_integration_test.go
+++ b/server/http_integration_test.go
@@ -1982,6 +1982,7 @@ func TestConfigBodyContentAccessControl(t *testing.T) {
 		{"/v2", http.Header{}, http.StatusUnauthorized, "application/json", "access control: ba1: missing credentials"},
 		{"/v3", http.Header{}, http.StatusOK, "application/json", ""},
 		{"/status", http.Header{}, http.StatusOK, "application/json", ""},
+		{"/v5/not-exist", http.Header{}, http.StatusUnauthorized, "application/json", "access control: ba1: missing credentials"},
 		{"/superadmin", http.Header{"Authorization": []string{"Basic OmFzZGY="}, "Auth": []string{"ba1", "ba4"}}, http.StatusOK, "application/json", ""},
 		{"/superadmin", http.Header{}, http.StatusUnauthorized, "application/json", "access control: ba1: missing credentials"},
 		{"/v4", http.Header{}, http.StatusUnauthorized, "text/html", "access control: ba1: missing credentials"},
diff --git a/server/testdata/integration/config/03_couper.hcl b/server/testdata/integration/config/03_couper.hcl
index 16d212b6..3e84fc8e 100644
--- a/server/testdata/integration/config/03_couper.hcl
+++ b/server/testdata/integration/config/03_couper.hcl
@@ -54,6 +54,17 @@ server "acs" {
     }
   }
 
+  api {
+    base_path = "/v5"
+    access_control = ["ba2"]
+    endpoint "/exists" {
+      error_file = "../server_error.html" # error_file in endpoint
+      proxy {
+        backend = "test"
+      }
+    }
+  }
+
   endpoint "/status" {
     disable_access_control = ["ba1"]
     proxy {