From a852ce291388a2d327e311bf3bee513f4513a706 Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 13:46:19 +0200 Subject: [PATCH 1/6] added allowedEndpoints --- .github/templates/README.template.md | 19 +++++++++++++- examples/config.yml | 2 ++ internals/proxy/middlewares/endpoints.go | 32 ++++++++++++++++++++++-- utils/config/loader.go | 3 +++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/.github/templates/README.template.md b/.github/templates/README.template.md index 57924fe6..2b310dd1 100644 --- a/.github/templates/README.template.md +++ b/.github/templates/README.template.md @@ -210,7 +210,7 @@ like Blocked Endpoints and any sort of Auth. > [!NOTE] > Blocked Endpoints can be reactivated by manually configuring them -### Blocked Endpoints +### Endpoints Because Secured Signal API is just a Proxy you can use all of the [Signal REST API](https://github.com/bbernhard/signal-cli-rest-api/blob/master/doc/EXAMPLES.md) endpoints except for... @@ -225,12 +225,29 @@ Because Secured Signal API is just a Proxy you can use all of the [Signal REST A | **/v1/accounts** | | **/v1/contacts** | +> [!NOTE] +> Matching works by checking if the requested Endpoints startswith a Blocked or Allowed Endpoint + These Endpoints are blocked by default due to Security Risks, but can be modified by setting `blockedEndpoints` in your config: ```yaml blockedEndpoints: [/v1/register, /v1/unregister, /v1/qrcodelink, /v1/contacts] ``` +Override Blocked Endpoints by explicitly allowing endpoints in `allowedEndpoints`. + +| Config (A) | (B) | Result | | | | +| :-------------------------- | :------------------------------- | :---------: | --- | :------------: | --- | +| `allowedEndpoints:` | | **all** | 🛑 | | | +| `blockedEndpoints:` | | **all** | ✅ | | | +| `allowedEndpoints:` | `blockedEndpoints: ["/v2/send"]` | **default** | ✅ | **`/v2/send`** | 🛑 | +| `blockedEndpoints:` | `allowedEndpoints: ["/v2/send"]` | **default** | 🛑 | **`/v2/send`** | ✅ | +| `blockedEndpoints: ["/v2"]` | `allowedEndpoints: ["/v2/send"]` | **`/v2*`** | 🛑 | **`/v2/send`** | ✅ | + +```yaml +allowedEndpoints: [/v2/send] +``` + ### Variables Placeholders can be added under `variables` and can then be referenced in the Body, Query or URL. diff --git a/examples/config.yml b/examples/config.yml index f8e24c36..2e5bb2c3 100644 --- a/examples/config.yml +++ b/examples/config.yml @@ -15,3 +15,5 @@ messageAliases: [{ alias: "msg", score: 100 }] blockedEndpoints: - /v1/about +allowedEndpoints: + - /v2/send diff --git a/internals/proxy/middlewares/endpoints.go b/internals/proxy/middlewares/endpoints.go index 173fff21..643da0c0 100644 --- a/internals/proxy/middlewares/endpoints.go +++ b/internals/proxy/middlewares/endpoints.go @@ -3,6 +3,7 @@ package middlewares import ( "net/http" "slices" + "strings" log "github.com/codeshelldev/secured-signal-api/utils/logger" ) @@ -15,7 +16,10 @@ func (data EndpointsMiddleware) Use() http.Handler { next := data.Next return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - blockedEndpoints := getSettingsByReq(req).BLOCKED_ENDPOINTS + settings := getSettingsByReq(req) + + blockedEndpoints := settings.BLOCKED_ENDPOINTS + allowedEndpoints := settings.ALLOWED_ENDPOINTS if blockedEndpoints == nil { blockedEndpoints = getSettings("*").BLOCKED_ENDPOINTS @@ -23,7 +27,7 @@ func (data EndpointsMiddleware) Use() http.Handler { reqPath := req.URL.Path - if slices.Contains(blockedEndpoints, reqPath) { + if isBlocked(reqPath, allowedEndpoints, blockedEndpoints) { log.Warn("User tried to access blocked endpoint: ", reqPath) http.Error(w, "Forbidden", http.StatusForbidden) return @@ -32,3 +36,27 @@ func (data EndpointsMiddleware) Use() http.Handler { next.ServeHTTP(w, req) }) } + +func isBlocked(endpoint string, allowed []string, blocked []string) bool { + var result bool + + if blocked == nil { + return false + } + + if allowed == nil { + return true + } + + isBlocked := slices.ContainsFunc(blocked, func(try string) bool { + return strings.HasPrefix(endpoint, try) + }) + + isExplictlyAllowed := slices.ContainsFunc(allowed, func(try string) bool { + return strings.HasPrefix(endpoint, try) + }) + + result = isBlocked && !isExplictlyAllowed + + return result +} \ No newline at end of file diff --git a/utils/config/loader.go b/utils/config/loader.go index be45893e..aec516ea 100644 --- a/utils/config/loader.go +++ b/utils/config/loader.go @@ -26,6 +26,7 @@ type ENV_ struct { type SETTING_ struct { BLOCKED_ENDPOINTS []string `koanf:"blockedendpoints"` + ALLOWED_ENDPOINTS []string `koanf:"allowedendpoints"` VARIABLES map[string]any `koanf:"variables"` MESSAGE_ALIASES []middlewareTypes.MessageAlias `koanf:"messagealiases"` } @@ -38,6 +39,7 @@ var ENV *ENV_ = &ENV_{ SETTINGS: map[string]*SETTING_{ "*": { BLOCKED_ENDPOINTS: []string{}, + ALLOWED_ENDPOINTS: []string{}, MESSAGE_ALIASES: []middlewareTypes.MessageAlias{}, VARIABLES: map[string]any{}, }, @@ -63,6 +65,7 @@ func InitEnv() { config.Unmarshal("variables", &defaultSettings.VARIABLES) defaultSettings.BLOCKED_ENDPOINTS = config.Strings("blockedendpoints") + defaultSettings.ALLOWED_ENDPOINTS = config.Strings("allowedendpoints") } func Load() { From ea44d51dc132f4d4d5c8233e5225a7bc8681383e Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 18:43:28 +0200 Subject: [PATCH 2/6] debug --- utils/config/loader.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/config/loader.go b/utils/config/loader.go index aec516ea..fa881b69 100644 --- a/utils/config/loader.go +++ b/utils/config/loader.go @@ -8,6 +8,7 @@ import ( "strings" middlewareTypes "github.com/codeshelldev/secured-signal-api/internals/proxy/middlewares/types" + "github.com/codeshelldev/secured-signal-api/utils" log "github.com/codeshelldev/secured-signal-api/utils/logger" "github.com/knadh/koanf/parsers/yaml" ) @@ -90,6 +91,8 @@ func Load() { InitEnv() log.Info("Finished Loading Configuration") + + log.Dev(utils.ToJson(config.All())) } func LoadDefaults() { From 991212c58b82f44cd5e2a8e47d9879a57f0eed47 Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 18:49:29 +0200 Subject: [PATCH 3/6] more dev debugging --- utils/config/loader.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/config/loader.go b/utils/config/loader.go index fa881b69..598f8060 100644 --- a/utils/config/loader.go +++ b/utils/config/loader.go @@ -92,7 +92,8 @@ func Load() { log.Info("Finished Loading Configuration") - log.Dev(utils.ToJson(config.All())) + log.Dev("Loaded Config:\n" + utils.ToJson(config.All())) + log.Dev("Loaded Token Configs:\n" + utils.ToJson(tokensLayer.All())) } func LoadDefaults() { From 3e76bffa509a4b3392b0814451ea12f5ad827a5d Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 19:23:05 +0200 Subject: [PATCH 4/6] fixed blocking logic --- .github/templates/README.template.md | 12 +++++----- internals/proxy/middlewares/endpoints.go | 28 +++++++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.github/templates/README.template.md b/.github/templates/README.template.md index 2b310dd1..2763833c 100644 --- a/.github/templates/README.template.md +++ b/.github/templates/README.template.md @@ -236,13 +236,11 @@ blockedEndpoints: [/v1/register, /v1/unregister, /v1/qrcodelink, /v1/contacts] Override Blocked Endpoints by explicitly allowing endpoints in `allowedEndpoints`. -| Config (A) | (B) | Result | | | | -| :-------------------------- | :------------------------------- | :---------: | --- | :------------: | --- | -| `allowedEndpoints:` | | **all** | 🛑 | | | -| `blockedEndpoints:` | | **all** | ✅ | | | -| `allowedEndpoints:` | `blockedEndpoints: ["/v2/send"]` | **default** | ✅ | **`/v2/send`** | 🛑 | -| `blockedEndpoints:` | `allowedEndpoints: ["/v2/send"]` | **default** | 🛑 | **`/v2/send`** | ✅ | -| `blockedEndpoints: ["/v2"]` | `allowedEndpoints: ["/v2/send"]` | **`/v2*`** | 🛑 | **`/v2/send`** | ✅ | +| Config (Allow) | (Block) | Result | | | | +| :------------------------------- | :---------------------------------- | :--------: | --- | :---------------: | --- | +| `allowedEndpoints: ["/v2/send"]` | `unset` | **all** | 🛑 | **`/v2/send`** | ✅ | +| `unset` | `blockedEndpoints: ["/v1/receive"]` | **all** | ✅ | **`/v1/receive`** | 🛑 | +| `blockedEndpoints: ["/v2"]` | `allowedEndpoints: ["/v2/send"]` | **`/v2*`** | 🛑 | **`/v2/send`** | ✅ | ```yaml allowedEndpoints: [/v2/send] diff --git a/internals/proxy/middlewares/endpoints.go b/internals/proxy/middlewares/endpoints.go index 643da0c0..5de4de0b 100644 --- a/internals/proxy/middlewares/endpoints.go +++ b/internals/proxy/middlewares/endpoints.go @@ -21,7 +21,7 @@ func (data EndpointsMiddleware) Use() http.Handler { blockedEndpoints := settings.BLOCKED_ENDPOINTS allowedEndpoints := settings.ALLOWED_ENDPOINTS - if blockedEndpoints == nil { + if blockedEndpoints == nil && allowedEndpoints == nil { blockedEndpoints = getSettings("*").BLOCKED_ENDPOINTS } @@ -38,17 +38,15 @@ func (data EndpointsMiddleware) Use() http.Handler { } func isBlocked(endpoint string, allowed []string, blocked []string) bool { - var result bool - if blocked == nil { - return false + blocked = []string{} } if allowed == nil { - return true + allowed = []string{} } - isBlocked := slices.ContainsFunc(blocked, func(try string) bool { + isExplicitlyBlocked := slices.ContainsFunc(blocked, func(try string) bool { return strings.HasPrefix(endpoint, try) }) @@ -56,7 +54,21 @@ func isBlocked(endpoint string, allowed []string, blocked []string) bool { return strings.HasPrefix(endpoint, try) }) - result = isBlocked && !isExplictlyAllowed + // Block all except explicitly Allowed + if len(blocked) == 0 && len(allowed) != 0 { + return !isExplictlyAllowed + } + + // Allow all except explicitly Blocked + if len(allowed) == 0 && len(blocked) != 0{ + return isExplicitlyBlocked + } + + // Excplicitly Blocked except excplictly Allowed + if len(blocked) != 0 && len(allowed) != 0 { + return isExplicitlyBlocked && !isExplictlyAllowed + } - return result + // Block all + return true } \ No newline at end of file From 70448e5d88f17b9edbb4b9f44a913d7089e12a36 Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 19:27:53 +0200 Subject: [PATCH 5/6] testing --- internals/proxy/middlewares/endpoints.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internals/proxy/middlewares/endpoints.go b/internals/proxy/middlewares/endpoints.go index 5de4de0b..2898849e 100644 --- a/internals/proxy/middlewares/endpoints.go +++ b/internals/proxy/middlewares/endpoints.go @@ -47,10 +47,12 @@ func isBlocked(endpoint string, allowed []string, blocked []string) bool { } isExplicitlyBlocked := slices.ContainsFunc(blocked, func(try string) bool { + log.Dev("Checking " + try + " against " + endpoint) return strings.HasPrefix(endpoint, try) }) isExplictlyAllowed := slices.ContainsFunc(allowed, func(try string) bool { + log.Dev("Checking " + try + " against " + endpoint) return strings.HasPrefix(endpoint, try) }) From 8486c723fc7b42d6cb9b7e44f28cfc955af073aa Mon Sep 17 00:00:00 2001 From: CodeShell <122738806+CodeShellDev@users.noreply.github.com> Date: Sun, 14 Sep 2025 19:32:21 +0200 Subject: [PATCH 6/6] finished testing --- internals/proxy/middlewares/endpoints.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internals/proxy/middlewares/endpoints.go b/internals/proxy/middlewares/endpoints.go index 2898849e..5de4de0b 100644 --- a/internals/proxy/middlewares/endpoints.go +++ b/internals/proxy/middlewares/endpoints.go @@ -47,12 +47,10 @@ func isBlocked(endpoint string, allowed []string, blocked []string) bool { } isExplicitlyBlocked := slices.ContainsFunc(blocked, func(try string) bool { - log.Dev("Checking " + try + " against " + endpoint) return strings.HasPrefix(endpoint, try) }) isExplictlyAllowed := slices.ContainsFunc(allowed, func(try string) bool { - log.Dev("Checking " + try + " against " + endpoint) return strings.HasPrefix(endpoint, try) })