Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic PR to nightly from 2023-06-12T14:11:27Z #5282

Merged
merged 49 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
192f67c
[Web] add cors to json_api
FreddleSpl0it Apr 26, 2023
6b82284
[Web] cors - add check if origin is valid
FreddleSpl0it Apr 26, 2023
9752313
logger pdo exception handling workaround
goodygh Apr 29, 2023
97a492b
[Rspamd] add dot-stuffing to bcc forwarding
FreddleSpl0it May 3, 2023
74bcec4
Merge pull request #5250 from mailcow/staging
DerLinkman May 25, 2023
7a582af
Rspamd returns 401 on unsuccesful logins
MAGICCC May 28, 2023
6f87539
[API] Update swagger version
MAGICCC May 28, 2023
490d553
Merge pull request #5264 from mailcow/staging
DerLinkman May 30, 2023
e691d2c
Merge pull request #5266 from mailcow/staging
DerLinkman May 30, 2023
06cce79
[Dockerapi] add pubsub handler for broadcasting in ha setup
FreddleSpl0it Jun 12, 2023
c873a14
Update thollander/actions-comment-pull-request action to v2.4.0 (#5280)
renovate[bot] Jun 12, 2023
61c8afa
Fix smtp settings for nextcloud v26
superpuffin Jun 13, 2023
6e1ee63
Update dependency nextcloud/server to v27
renovate[bot] Jun 13, 2023
42a91af
[API] Update swagger version
MAGICCC Jun 15, 2023
c0c46b7
[API] Update swagger version
MAGICCC Jun 19, 2023
1de4707
Added DQS Values to update.sh/generate + check of variable
DerLinkman Jun 23, 2023
bf6a61f
Small corrections to update/generate.sh
DerLinkman Jun 23, 2023
03b7a8d
Implemented Postfix Blocklist generation
DerLinkman Jun 23, 2023
380cdab
Removed dnsbl from main.cf
DerLinkman Jun 23, 2023
408381b
Update Postfix image to 1.69 + improvements
DerLinkman Jun 23, 2023
7b64530
Added Colorful Outputs for the Spamhaus info in PF
DerLinkman Jun 23, 2023
689856b
New Symbols defined for Security ClamAV DBs
DerLinkman Jun 23, 2023
8cd4ae1
Improved Scores
DerLinkman Jun 23, 2023
6e9c024
Changed weight to score for CLAMD_SPAM
DerLinkman Jun 27, 2023
3b748a3
Merge pull request #5284 from mailcow:renovate/nextcloud-server-27.x
DerLinkman Jun 27, 2023
0863bff
Merge pull request #5283 from superpuffin:master
DerLinkman Jun 27, 2023
14265f3
Merge pull request #5263 from mailcow:update-api
DerLinkman Jun 27, 2023
29892dc
Merge pull request #5262 from mailcow/fix-5252
DerLinkman Jun 27, 2023
0f69565
[Web] add CLUSTERMODE environment variable
FreddleSpl0it Jul 7, 2023
0f0d43b
[Dockerapi] add missing import os
FreddleSpl0it Jul 7, 2023
8984509
Merge pull request #5213 from mailcow/feat/cors
FreddleSpl0it Jul 7, 2023
cb1a11e
[Web] fix rspamd-history
FreddleSpl0it Jul 10, 2023
722134e
Merge pull request #5312 from mailcow/fix/ui-logs
FreddleSpl0it Jul 10, 2023
da8e496
Merge pull request #5310 from mailcow/feat/ha-pubsub
FreddleSpl0it Jul 10, 2023
a0723f6
Merge pull request #5221 from mailcow/fix/dot-stuffing-bcc
FreddleSpl0it Jul 10, 2023
cf239dd
Merge pull request #5215 from goodygh/5136-fix-logger-error-handling
FreddleSpl0it Jul 10, 2023
b903cf3
Fixes several instances of missing </span>, extra role='tabpanel' and…
Jul 11, 2023
2b009c7
Merge pull request #5316 from mailcow/feat/rspamd-securite-symbols
DerLinkman Jul 12, 2023
03580cb
Merge pull request #5315 from SnailShea/fix/twig-typos
FreddleSpl0it Jul 12, 2023
ec8d298
Update postfix.sh to include pbl for dqs
DerLinkman Jul 13, 2023
521120a
Update dependency nextcloud/server to v27.0.1 (#5324)
renovate[bot] Jul 24, 2023
0383114
[Web] fix visual bug #5322
FreddleSpl0it Jul 27, 2023
cd635ec
[Dockerapi] Update to 2.05
FreddleSpl0it Jul 27, 2023
9c44b5e
[Web] display is_catch_all and aliases_send_as_all if not empty #5320
FreddleSpl0it Jul 27, 2023
3814c32
[Web] add edit/cors api endpoint to swagger
FreddleSpl0it Jul 27, 2023
b9867e3
[Web] change style of f2b active ban actions
FreddleSpl0it Jul 27, 2023
1140797
[Web] change style of f2b active ban actions
FreddleSpl0it Jul 27, 2023
815572f
Merge branch 'feat/spamhaus-dqs-asn' into staging
DerLinkman Jul 28, 2023
731fabe
Fixed Syntax error in generate_config.sh
DerLinkman Jul 28, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/check_prs_if_on_staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging
steps:
- name: Send message
uses: thollander/actions-comment-pull-request@v2.3.1
uses: thollander/actions-comment-pull-request@v2.4.0
with:
GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }}
message: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data/conf/postfix/extra.cf
data/conf/postfix/sni.map
data/conf/postfix/sni.map.db
data/conf/postfix/sql
data/conf/postfix/dns_blocklists.cf
data/conf/rspamd/custom/*
data/conf/rspamd/local.d/*
data/conf/rspamd/override.d/*
Expand Down
7 changes: 5 additions & 2 deletions data/Dockerfiles/dockerapi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ RUN apk add --update --no-cache python3 \
uvicorn \
aiodocker \
docker \
redis
aioredis
RUN mkdir /app/modules

COPY docker-entrypoint.sh /app/
COPY dockerapi.py /app/
COPY main.py /app/main.py
COPY modules/ /app/modules/

ENTRYPOINT ["/bin/sh", "/app/docker-entrypoint.sh"]
CMD exec python main.py
2 changes: 1 addition & 1 deletion data/Dockerfiles/dockerapi/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
-subj /CN=dockerapi/O=mailcow \
-addext subjectAltName=DNS:dockerapi`

`uvicorn --host 0.0.0.0 --port 443 --ssl-certfile=/app/dockerapi_cert.pem --ssl-keyfile=/app/dockerapi_key.pem dockerapi:app`
exec "$@"
549 changes: 0 additions & 549 deletions data/Dockerfiles/dockerapi/dockerapi.py

This file was deleted.

260 changes: 260 additions & 0 deletions data/Dockerfiles/dockerapi/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import os
import sys
import uvicorn
import json
import uuid
import async_timeout
import asyncio
import aioredis
import aiodocker
import docker
import logging
from logging.config import dictConfig
from fastapi import FastAPI, Response, Request
from modules.DockerApi import DockerApi

dockerapi = None
app = FastAPI()

# Define Routes
@app.get("/host/stats")
async def get_host_update_stats():
global dockerapi

if dockerapi.host_stats_isUpdating == False:
asyncio.create_task(dockerapi.get_host_stats())
dockerapi.host_stats_isUpdating = True

while True:
if await dockerapi.redis_client.exists('host_stats'):
break
await asyncio.sleep(1.5)

stats = json.loads(await dockerapi.redis_client.get('host_stats'))
return Response(content=json.dumps(stats, indent=4), media_type="application/json")

@app.get("/containers/{container_id}/json")
async def get_container(container_id : str):
global dockerapi

if container_id and container_id.isalnum():
try:
for container in (await dockerapi.async_docker_client.containers.list()):
if container._id == container_id:
container_info = await container.show()
return Response(content=json.dumps(container_info, indent=4), media_type="application/json")

res = {
"type": "danger",
"msg": "no container found"
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")
except Exception as e:
res = {
"type": "danger",
"msg": str(e)
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")
else:
res = {
"type": "danger",
"msg": "no or invalid id defined"
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")

@app.get("/containers/json")
async def get_containers():
global dockerapi

containers = {}
try:
for container in (await dockerapi.async_docker_client.containers.list()):
container_info = await container.show()
containers.update({container_info['Id']: container_info})
return Response(content=json.dumps(containers, indent=4), media_type="application/json")
except Exception as e:
res = {
"type": "danger",
"msg": str(e)
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")

@app.post("/containers/{container_id}/{post_action}")
async def post_containers(container_id : str, post_action : str, request: Request):
global dockerapi

try :
request_json = await request.json()
except Exception as err:
request_json = {}

if container_id and container_id.isalnum() and post_action:
try:
"""Dispatch container_post api call"""
if post_action == 'exec':
if not request_json or not 'cmd' in request_json:
res = {
"type": "danger",
"msg": "cmd is missing"
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")
if not request_json or not 'task' in request_json:
res = {
"type": "danger",
"msg": "task is missing"
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")

api_call_method_name = '__'.join(['container_post', str(post_action), str(request_json['cmd']), str(request_json['task']) ])
else:
api_call_method_name = '__'.join(['container_post', str(post_action) ])

api_call_method = getattr(dockerapi, api_call_method_name, lambda container_id: Response(content=json.dumps({'type': 'danger', 'msg':'container_post - unknown api call' }, indent=4), media_type="application/json"))

dockerapi.logger.info("api call: %s, container_id: %s" % (api_call_method_name, container_id))
return api_call_method(request_json, container_id=container_id)
except Exception as e:
dockerapi.logger.error("error - container_post: %s" % str(e))
res = {
"type": "danger",
"msg": str(e)
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")

else:
res = {
"type": "danger",
"msg": "invalid container id or missing action"
}
return Response(content=json.dumps(res, indent=4), media_type="application/json")

@app.post("/container/{container_id}/stats/update")
async def post_container_update_stats(container_id : str):
global dockerapi

# start update task for container if no task is running
if container_id not in dockerapi.containerIds_to_update:
asyncio.create_task(dockerapi.get_container_stats(container_id))
dockerapi.containerIds_to_update.append(container_id)

while True:
if await dockerapi.redis_client.exists(container_id + '_stats'):
break
await asyncio.sleep(1.5)

stats = json.loads(await dockerapi.redis_client.get(container_id + '_stats'))
return Response(content=json.dumps(stats, indent=4), media_type="application/json")

# Events
@app.on_event("startup")
async def startup_event():
global dockerapi

# Initialize a custom logger
logger = logging.getLogger("dockerapi")
logger.setLevel(logging.INFO)
# Configure the logger to output logs to the terminal
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(levelname)s: %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

logger.info("Init APP")

# Init redis client
if os.environ['REDIS_SLAVEOF_IP'] != "":
redis_client = redis = await aioredis.from_url(f"redis://{os.environ['REDIS_SLAVEOF_IP']}:{os.environ['REDIS_SLAVEOF_PORT']}/0")
else:
redis_client = redis = await aioredis.from_url("redis://redis-mailcow:6379/0")

# Init docker clients
sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
async_docker_client = aiodocker.Docker(url='unix:///var/run/docker.sock')

dockerapi = DockerApi(redis_client, sync_docker_client, async_docker_client, logger)

logger.info("Subscribe to redis channel")
# Subscribe to redis channel
dockerapi.pubsub = redis.pubsub()
await dockerapi.pubsub.subscribe("MC_CHANNEL")
asyncio.create_task(handle_pubsub_messages(dockerapi.pubsub))

@app.on_event("shutdown")
async def shutdown_event():
global dockerapi

# Close docker connections
dockerapi.sync_docker_client.close()
await dockerapi.async_docker_client.close()

# Close redis
await dockerapi.pubsub.unsubscribe("MC_CHANNEL")
await dockerapi.redis_client.close()

# PubSub Handler
async def handle_pubsub_messages(channel: aioredis.client.PubSub):
global dockerapi

while True:
try:
async with async_timeout.timeout(1):
message = await channel.get_message(ignore_subscribe_messages=True)
if message is not None:
# Parse message
data_json = json.loads(message['data'].decode('utf-8'))
dockerapi.logger.info(f"PubSub Received - {json.dumps(data_json)}")

# Handle api_call
if 'api_call' in data_json:
# api_call: container_post
if data_json['api_call'] == "container_post":
if 'post_action' in data_json and 'container_name' in data_json:
try:
"""Dispatch container_post api call"""
request_json = {}
if data_json['post_action'] == 'exec':
if 'request' in data_json:
request_json = data_json['request']
if 'cmd' in request_json:
if 'task' in request_json:
api_call_method_name = '__'.join(['container_post', str(data_json['post_action']), str(request_json['cmd']), str(request_json['task']) ])
else:
dockerapi.logger.error("api call: task missing")
else:
dockerapi.logger.error("api call: cmd missing")
else:
dockerapi.logger.error("api call: request missing")
else:
api_call_method_name = '__'.join(['container_post', str(data_json['post_action'])])

if api_call_method_name:
api_call_method = getattr(dockerapi, api_call_method_name)
if api_call_method:
dockerapi.logger.info("api call: %s, container_name: %s" % (api_call_method_name, data_json['container_name']))
api_call_method(request_json, container_name=data_json['container_name'])
else:
dockerapi.logger.error("api call not found: %s, container_name: %s" % (api_call_method_name, data_json['container_name']))
except Exception as e:
dockerapi.logger.error("container_post: %s" % str(e))
else:
dockerapi.logger.error("api call: missing container_name, post_action or request")
else:
dockerapi.logger.error("Unknwon PubSub recieved - %s" % json.dumps(data_json))
else:
dockerapi.logger.error("Unknwon PubSub recieved - %s" % json.dumps(data_json))

await asyncio.sleep(0.01)
except asyncio.TimeoutError:
pass

if __name__ == '__main__':
uvicorn.run(
app,
host="0.0.0.0",
port=443,
ssl_certfile="/app/dockerapi_cert.pem",
ssl_keyfile="/app/dockerapi_key.pem",
log_level="info",
loop="none"
)
Loading
Loading