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
9 changes: 1 addition & 8 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
.gitignore
.git
.github
.env
docker-compose.yaml
LICENSE
*.md
.venv
!*.py
51 changes: 50 additions & 1 deletion .github/templates/README.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,65 @@ Get the latest version of the `docker-compose.yaml` file:
{ { file.docker-compose.yaml } }
```

### Reverse proxy

Take a look at traefik implementation:

```yaml
{ { file.examples/traefik.docker-compose.yaml } }
```

## Setup

Before you can send messages via `secured-signal-api` you must first setup [`signal-api`](https://github.com/bbernhard/signal-cli-rest-api/blob/master/doc/EXAMPLES.md),

to send messages you have to either:

- register a Signal Account

OR

- link Signal Api to a already registered Signal Device

## Usage

To send a message to `number`: `1234567`:

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

### Configuration

Because `secured-signal-api` is just a secure proxy you can use all of the [Signal REST Api](https://github.com/bbernhard/signal-cli-rest-api/blob/master/doc/EXAMPLES.md) endpoints with an Exception of:

```python
DEFAULT_BLOCKED_ENDPOINTS = [
"/v1/about",
"/v1/configuration",
"/v1/devices",
"/v1/register",
"/v1/unregister",
"/v1/qrcodelink",
"/v1/accounts",
"/v1/contacts"
]
```

Which are blocked by default to increase Security, but you these can be modified by setting the `BLOCKED_ENDPOINTS` environment variable as a valid json array

```yaml
environment:
BLOCKED_ENDPOINTS: '[ "/v1/register","/v1/unregister","/v1/qrcodelink","/v1/contacts" ]'
```

## Contributing

Found a bug? Want to change or add something?
Feel free to open up an issue or create a Pull Request!

_This is a small project so don't expect any huge changes in the future_

## License

[MIT](https://choosealicense.com/licenses/mit/)
1 change: 1 addition & 0 deletions .github/workflows/readme-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths:
- "docker-compose.yaml"
- ".github/templates/README.template.md"
- "examples/*"

jobs:
update-readme:
Expand Down
111 changes: 108 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,125 @@ Get the latest version of the `docker-compose.yaml` file:
```yaml
---
services:
myservice:
container_name: myservice
signal-api:
image: bbernhard/signal-cli-rest-api
container_name: signal-api
environment:
- MODE=normal
volumes:
- ./data:/home/.local/share/signal-cli
networks:
backend:
aliases:
- signal-api
restart: unless-stopped

secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api
container_name: secured-signal
networks:
backend:
aliases:
- secured-signal-api
environment:
SIGNAL_API_URL: http://signal-api:8080
DEFAULT_RECIPIENTS: '[ "000", "001", "002" ]'
SENDER: 123456789
ports:
- "8880:8880"
restart: unless-stopped

networks:
backend:
```

### Reverse proxy

Take a look at traefik implementation:

```yaml
services:
# ...
secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api
container_name: secured-signal
networks:
proxy:
backend:
aliases:
- secured-signal-api
environment:
SIGNAL_API_URL: http://signal-api:8080
DEFAULT_RECIPIENTS: '[ "000", "001", "002" ]'
SENDER: 123456789
labels:
- traefik.enable=true
- traefik.http.routers.signal-api.rule=Host(`signal-api.mydomain.com`)
- traefik.http.routers.signal-api.entrypoints=websecure
- traefik.http.routers.signal-api.tls=true
- traefik.http.routers.signal-api.tls.certresolver=cloudflare
- traefik.http.routers.signal-api.service=signal-api-svc
- traefik.http.services.signal-api-svc.loadbalancer.server.port=8880
- traefik.docker.network=proxy
restart: unless-stopped

networks:
backend:
proxy:
external: true
```

## Setup

Before you can send messages via `secured-signal-api` you must first setup [`signal-api`](https://github.com/bbernhard/signal-cli-rest-api/blob/master/doc/EXAMPLES.md),

to send messages you have to either:

- register a Signal Account

OR

- link Signal Api to a already registered Signal Device

## Usage

To send a message to `number`: `1234567`:

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

### Configuration

Because `secured-signal-api` is just a secure proxy you can use all of the [Signal REST Api](https://github.com/bbernhard/signal-cli-rest-api/blob/master/doc/EXAMPLES.md) endpoints with an Exception of:

```python
DEFAULT_BLOCKED_ENDPOINTS = [
"/v1/about",
"/v1/configuration",
"/v1/devices",
"/v1/register",
"/v1/unregister",
"/v1/qrcodelink",
"/v1/accounts",
"/v1/contacts"
]
```

Which are blocked by default to increase Security, but you these can be modified by setting the `BLOCKED_ENDPOINTS` environment variable as a valid json array

```yaml
environment:
BLOCKED_ENDPOINTS: '[ "/v1/register","/v1/unregister","/v1/qrcodelink","/v1/contacts" ]'
```

## Contributing

Found a bug? Want to change or add something?
Feel free to open up an issue or create a Pull Request!

_This is a small project so don't expect any huge changes in the future_

## License

[MIT](https://choosealicense.com/licenses/mit/)
24 changes: 15 additions & 9 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import requests
import re
import base64
import logging
import logging
from urllib.parse import unquote

app = Flask("Secured Signal Api")

Expand Down Expand Up @@ -39,7 +40,7 @@ def fillInVars(obj):
for i in range(len(obj)):
obj[i] = fillInVars(obj[i])
elif isinstance(obj, str):
matches = re.findall(r"\${(.*?)}", obj)
matches = re.findall(r"\${(.*?)}", obj)
for match in matches:
if match in VARIABLES:
value = VARIABLES[match]
Expand Down Expand Up @@ -75,15 +76,20 @@ def middlewares():
auth_header = request.headers.get("Authorization", "")

if auth_header.startswith("Bearer "):
token = auth_header.split(" ", 1)[1]
if token != API_TOKEN:
token = auth_header.split(" ", 1)[1]

token = unquote(token)
if token != API_TOKEN:
infoLog(f"Client failed Bearer Auth [token: {token}]")
return UnauthorizedResponse()
elif auth_header.startswith("Basic "):
try:
decoded = base64.b64decode(auth_header.split(" ", 1)[1]).decode()
username, password = decoded.split(":", 1)
if username != "api" or password != API_TOKEN:
elif auth_header.startswith("Basic "):
try:
decoded = base64.b64decode(auth_header.split(" ", 1)[1]).decode()
username, password = decoded.split(":", 1)

username = unquote(username)
password = unquote(password)
if username != "api" or password != API_TOKEN:
infoLog(f"Client failed Basic Auth [user: {username}, pw:{password}]")
return UnauthorizedResponse()
except Exception as error:
Expand Down
32 changes: 30 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
---
services:
myservice:
container_name: myservice
signal-api:
image: bbernhard/signal-cli-rest-api
container_name: signal-api
environment:
- MODE=normal
volumes:
- ./data:/home/.local/share/signal-cli
networks:
backend:
aliases:
- signal-api
restart: unless-stopped

secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api
container_name: secured-signal
networks:
backend:
aliases:
- secured-signal-api
environment:
SIGNAL_API_URL: http://signal-api:8080
DEFAULT_RECIPIENTS: '[ "000", "001", "002" ]'
SENDER: 123456789
ports:
- "8880:8880"
restart: unless-stopped

networks:
backend:
29 changes: 29 additions & 0 deletions examples/traefik.docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
# ...
secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api
container_name: secured-signal
networks:
proxy:
backend:
aliases:
- secured-signal-api
environment:
SIGNAL_API_URL: http://signal-api:8080
DEFAULT_RECIPIENTS: '[ "000", "001", "002" ]'
SENDER: 123456789
labels:
- traefik.enable=true
- traefik.http.routers.signal-api.rule=Host(`signal-api.mydomain.com`)
- traefik.http.routers.signal-api.entrypoints=websecure
- traefik.http.routers.signal-api.tls=true
- traefik.http.routers.signal-api.tls.certresolver=cloudflare
- traefik.http.routers.signal-api.service=signal-api-svc
- traefik.http.services.signal-api-svc.loadbalancer.server.port=8880
- traefik.docker.network=proxy
restart: unless-stopped

networks:
backend:
proxy:
external: true