Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 45 additions & 51 deletions .github/templates/README.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ Notice the `@` infront of `authorization`. See [KeyValue Pair Injection](#keyval

### Example

To send a message to 1234567:
To send a message to `+123400002`:

```bash
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer API_TOKEN" -d '{"message": "Hello World!", "recipients": ["1234567"]}' http://sec-signal-api:8880/v2/send
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer API_TOKEN" -d '{"message": "Hello World!", "recipients": ["+123400002"]}' http://sec-signal-api:8880/v2/send
```

### Advanced
Expand Down Expand Up @@ -160,10 +160,10 @@ Suppose you want to set a new [Placeholder](#placeholders) `NUMBER` in your Envi

```yaml
environment:
VARIABLES__NUMBER: "000"
SETTINGS__VARIABLES__NUMBER: "+123400001"
```

This would internally be converted into `variables.number` matching the config formatting.
This would internally be converted into `settings.variables.number` matching the config formatting.

> [!IMPORTANT]
> Underscores `_` are removed during Conversion, Double Underscores `__` on the other hand convert the Variable into a nested Object (`__` replaced by `.`)
Expand Down Expand Up @@ -200,52 +200,48 @@ api:
```

> [!IMPORTANT]
> It is highly recommended use API Tokens

> _What if I just don't?_

Secured Signal API will still work, but important Security Features won't be available
like Blocked Endpoints and any sort of Auth.
> Using API Tokens is highly recommended, but not mandatory.
> Some important Security Features won't be available (like default Blocked Endpoints).

> [!NOTE]
> Blocked Endpoints can be reactivated by manually configuring them

### 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...
Since 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...

| Endpoint | |
| :-------------------- | ------------------ |
| **/v1/about** | **/v1/unregister** |
| **/v1/configuration** | **/v1/qrcodelink** |
| **/v1/devives** | **/v1/contacts** |
| **/v1/register** | **/v1/accounts** |

| Endpoint |
| :-------------------- |
| **/v1/about** |
| **/v1/configuration** |
| **/v1/devives** |
| **/v1/register** |
| **/v1/unregister** |
| **/v1/qrcodelink** |
| **/v1/accounts** |
| **/v1/contacts** |
These Endpoints are blocked by default due to Security Risks.

> [!NOTE]
> Matching works by checking if the requested Endpoints startswith a Blocked or Allowed Endpoint
> Matching works by checking if the requested Endpoints starts with a Blocked or an Allowed Endpoint

These Endpoints are blocked by default due to Security Risks, but can be modified by setting `blockedEndpoints` in your config:
You can modify Blocked Endpoints by configuring `blockedEndpoints` in your config:

```yaml
blockedEndpoints: [/v1/register, /v1/unregister, /v1/qrcodelink, /v1/contacts]
settings:
blockedEndpoints: [/v1/register, /v1/unregister, /v1/qrcodelink, /v1/contacts]
```

Override Blocked Endpoints by explicitly allowing endpoints in `allowedEndpoints`.
You can also override Blocked Endpoints by adding Allowed Endpoints to `allowedEndpoints`.

```yaml
settings:
allowedEndpoints: [/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]
```

### Variables

Placeholders can be added under `variables` and can then be referenced in the Body, Query or URL.
Expand All @@ -256,40 +252,38 @@ See [Placeholders](#placeholders).
> Example: `number` becomes `NUMBER` in `{{.NUMBER}}`

```yaml
variables:
number: "001",
recipients: [
"user.id", "000", "001", "group.id"
]
settings:
variables:
number: "+123400001",
recipients: ["+123400002", "group.id", "user.id"]
```

### Message Aliases

To improve compatibility with other services Secured Signal API provides aliases for the `message` attribute by default:

| Alias | Score |
| ----------- | ----- |
| msg | 100 |
| content | 99 |
| description | 98 |
| text | 20 |
| body | 15 |
| summary | 10 |
| details | 9 |
| payload | 2 |
| data | 1 |
| Alias | Score | Alias | Score |
| ------------ | ----- | ---------------- | ----- |
| msg | 100 | data.content | 9 |
| content | 99 | data.description | 8 |
| description | 98 | data.text | 7 |
| text | 20 | data.summary | 6 |
| summary | 15 | data.details | 5 |
| details | 14 | body | 2 |
| data.message | 10 | data | 1 |

Secured Signal API will pick the best scoring Message Alias (if available) to extract the correct message from the Request Body.

Message Aliases can be added by setting `messageAliases` in your config:

```yaml
messageAliases:
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
settings:
messageAliases:
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
```

### Port
Expand Down
62 changes: 31 additions & 31 deletions config/defaults.yml
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
server:
port: 8880

logLevel: INFO
logLevel: info

messageAliases:
[
{ alias: msg, score: 100 },
{ alias: content, score: 99 },
{ alias: description, score: 98 },
{ alias: text, score: 20 },
{ alias: summary, score: 15 },
{ alias: details, score: 14 },
settings:
messageAliases:
[
{ alias: msg, score: 100 },
{ alias: content, score: 99 },
{ alias: description, score: 98 },
{ alias: text, score: 20 },
{ alias: summary, score: 15 },
{ alias: details, score: 14 },

{ alias: data.message, score: 10 },
{ alias: data.content, score: 9 },
{ alias: data.description, score: 8 },
{ alias: data.text, score: 7 },
{ alias: data.summary, score: 6 },
{ alias: data.details, score: 5 },
{ alias: data.message, score: 10 },
{ alias: data.content, score: 9 },
{ alias: data.description, score: 8 },
{ alias: data.text, score: 7 },
{ alias: data.summary, score: 6 },
{ alias: data.details, score: 5 },

{ alias: payload, score: 3 },
{ alias: body, score: 2 },
{ alias: data, score: 1 },
]
{ alias: body, score: 2 },
{ alias: data, score: 1 },
]

variables:
recipients: ${RECIPIENTS}
number: ${NUMBER}
variables:
recipients: ${RECIPIENTS}
number: ${NUMBER}

blockedEndpoints:
- /v1/about
- /v1/configuration
- /v1/devices
- /v1/register
- /v1/unregister
- /v1/qrcodelink
- /v1/accounts
- /v1/contacts
blockedEndpoints:
- /v1/about
- /v1/configuration
- /v1/devices
- /v1/register
- /v1/unregister
- /v1/qrcodelink
- /v1/accounts
- /v1/contacts
17 changes: 9 additions & 8 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,28 @@ services:
- MODE=normal
volumes:
- ./data:/home/.local/share/signal-cli
restart: unless-stopped
networks:
backend:
aliases:
- signal-api
restart: unless-stopped

secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api:latest
container_name: secured-signal
networks:
backend:
aliases:
- secured-signal-api
environment:
API__URL: http://signal-api:8080
VARIABLES__RECIPIENTS: '[000,001,002]'
VARIABLES__NUMBER: 123456789
API__TOKENS: '[LOOOOOONG_STRING]'
SETTINGS__VARIABLES__RECIPIENTS:
["+123400002", "+123400003", "+123400004"]
SETTINGS__VARIABLES__NUMBER: "+123400001"
API__TOKENS: [LOOOOOONG_STRING]
ports:
- "8880:8880"
restart: unless-stopped
networks:
backend:
aliases:
- secured-signal-api

networks:
backend:
17 changes: 9 additions & 8 deletions examples/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ api:

logLevel: INFO

variables:
number: "000"
recipients: ["001", "group.id", "user.id"]
settings:
variables:
number: "+123400001"
recipients: ["+123400002", "group.id", "user.id"]

messageAliases: [{ alias: "msg", score: 100 }]
messageAliases: [{ alias: "msg", score: 100 }]

blockedEndpoints:
- /v1/about
allowedEndpoints:
- /v2/send
blockedEndpoints:
- /v1/about
allowedEndpoints:
- /v2/send
16 changes: 8 additions & 8 deletions examples/traefik.docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ services:
secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api:latest
container_name: secured-signal
networks:
proxy:
backend:
aliases:
- secured-signal-api
environment:
API__URL: http://signal-api:8080
VARIABLES__RECIPIENTS: '[000,001,002]'
VARIABLES__NUMBER: 123456789
API__TOKENS: '[LOOOOOONG_STRING]'
SETTINGS__VARIABLES__RECIPIENTS: ["123400002", "123400003", "123400004"]
SETTINGS__VARIABLES__NUMBER: "+123400001"
API__TOKENS: [LOOOOOONG_STRING]
labels:
- traefik.enable=true
- traefik.http.routers.signal-api.rule=Host(`signal-api.mydomain.com`)
Expand All @@ -22,6 +17,11 @@ services:
- traefik.http.services.signal-api-svc.loadbalancer.server.port=8880
- traefik.docker.network=proxy
restart: unless-stopped
networks:
proxy:
backend:
aliases:
- secured-signal-api

networks:
backend:
Expand Down
9 changes: 3 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ module github.com/codeshelldev/secured-signal-api

go 1.25.1

require (
go.uber.org/zap v1.27.0
gopkg.in/yaml.v3 v3.0.1
)
require go.uber.org/zap v1.27.0

require (
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/confmap v1.0.0
github.com/knadh/koanf/providers/env/v2 v2.0.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/v2 v2.2.2
github.com/knadh/koanf/v2 v2.3.0
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
Expand All @@ -14,8 +14,8 @@ github.com/knadh/koanf/providers/env/v2 v2.0.0 h1:Ad5H3eun722u+FvchiIcEIJZsZ2M6o
github.com/knadh/koanf/providers/env/v2 v2.0.0/go.mod h1:1g01PE+Ve1gBfWNNw2wmULRP0tc8RJrjn5p2N/jNCIc=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/v2 v2.2.2 h1:ghbduIkpFui3L587wavneC9e3WIliCgiCgdxYO/wd7A=
github.com/knadh/koanf/v2 v2.2.2/go.mod h1:abWQc0cBXLSF/PSOMCB/SK+T13NXDsPvOksbpi5e/9Q=
github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM=
github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down
4 changes: 2 additions & 2 deletions internals/proxy/middlewares/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strconv"

middlewareTypes "github.com/codeshelldev/secured-signal-api/internals/proxy/middlewares/types"
"github.com/codeshelldev/secured-signal-api/utils"
jsonutils "github.com/codeshelldev/secured-signal-api/utils/jsonutils"
log "github.com/codeshelldev/secured-signal-api/utils/logger"
request "github.com/codeshelldev/secured-signal-api/utils/request"
)
Expand Down Expand Up @@ -90,7 +90,7 @@ func getMessage(aliases []middlewareTypes.MessageAlias, data map[string]any) (st
func processAlias(alias middlewareTypes.MessageAlias, data map[string]any) (string, int, bool) {
aliasKey := alias.Alias

value, ok := utils.GetByPath(aliasKey, data)
value, ok := jsonutils.GetByPath(aliasKey, data)

aliasValue, isStr := value.(string)

Expand Down
Loading