Skip to content
Closed
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
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
FROM golang:1.24-bookworm AS gobuild

WORKDIR /code

COPY seeding/. .
RUN go build -o app automod.go

FROM python:3.12-slim

WORKDIR /code
Expand All @@ -13,5 +20,6 @@ RUN chmod +x entrypoint.sh
RUN chmod +x manage.py
RUN chmod +x rconweb/manage.py
ENV LOGGING_FILENAME=startup.log
COPY --from=gobuild /code/app /code/seeding/

ENTRYPOINT [ "/code/entrypoint.sh" ]
8 changes: 8 additions & 0 deletions config/supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ startretries=5
autostart=true
autorestart=unexpected

[program:enforce_cap_fight]
command=/code/seeding/app
startretries=5
autostart=true
autorestart=unexpected
stderror_logfile=/logs/enforce_cap_fight.log
stdout_logfile=/logs/enforce_cap_fight.log

[program:cron]
environment=LOGGING_FILENAME=cron_%(ENV_SERVER_NUMBER)s.log
command=/bin/bash -c "/usr/bin/crontab /config/crontab && /usr/sbin/cron -f"
Expand Down
53 changes: 50 additions & 3 deletions rconweb/api/auth.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import csv
import datetime
import hashlib
import hmac
import json
import logging
import os
from dataclasses import asdict, dataclass
from functools import wraps
from typing import Any, Sequence
Expand All @@ -18,14 +21,13 @@
from django.db.models.signals import post_delete, post_save
from django.http import HttpResponse, QueryDict, parse_cookie
from django.views.decorators.csrf import csrf_exempt
from rconweb.settings import SECRET_KEY, TAG_VERSION

from rcon.audit import heartbeat, set_registered_mods
from rcon.cache_utils import ttl_cache, invalidates
from rcon.settings import SERVER_INFO
from rcon.types import DjangoGroup, DjangoPermission, DjangoUserPermissions
from rcon.user_config.rcon_server_settings import RconServerSettingsUserConfig
from rconweb.settings import SECRET_KEY, TAG_VERSION


from .decorators import require_content_type, require_http_methods
from .models import DjangoAPIKey, SteamPlayer

Expand Down Expand Up @@ -289,6 +291,50 @@ def check_api_key(request):
pass


class InternalUser(User):
"""
Represents a system-user, which uses the CRCon API internally.
This should only ever be used for components that cannot directly invoke the corresponding python APIs directly.
"""

def has_perms(self, perm_list, obj=None) -> bool:
return True


def check_internal_api(request):
"""
Verifies if a request is coming from an internal user, such as the seeding automod in golang.
The user does not have password, and is not included in the standard Django API key or User list.
Everyone with this API key will automatically have every permission available.

The API key is automatically generated from the provided HLL server password and the backend API secret key and
can therefore be automatically created on the user side as well, whenever needed, in a container that shares the same
environment variables.
"""
logger.info("Checking internal")
try:
logger.info(SECRET_KEY)
logger.info(SERVER_INFO.get("password"))
header_name, raw_api_key = request.META[HTTP_AUTHORIZATION_HEADER].split(
maxsplit=1
)
logger.info(header_name)
logger.info(raw_api_key)
if not header_name.upper().strip() in BEARER:
return
api_key = hmac.new(
SECRET_KEY.encode(),
msg=SERVER_INFO.get("password").encode(),
digestmod=hashlib.sha256
).hexdigest().upper()
if raw_api_key == api_key:
request.user = InternalUser(username="system")

except (KeyError, ValueError) as e:
logger.error("", e)
pass


def login_required():
"""Flag this endpoint as one that requires the user
to be logged in.
Expand All @@ -297,6 +343,7 @@ def login_required():
def decorator(func):
@wraps(func)
def wrapper(request, *args, **kwargs):
check_internal_api(request)
# Check if API-Key is used
check_api_key(request)

Expand Down
Loading