Files
tacticalrmm/api/tacticalrmm/logs/views.py
2020-12-02 11:05:29 +00:00

194 lines
6.1 KiB
Python

import asyncio
import subprocess
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from django.utils import timezone as djangotime
from django.db.models import Q
from django.core.paginator import Paginator
from datetime import datetime as dt
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from .models import PendingAction, AuditLog
from agents.models import Agent
from accounts.models import User
from .serializers import PendingActionSerializer, AuditLogSerializer
from agents.serializers import AgentHostnameSerializer
from accounts.serializers import UserSerializer
from tacticalrmm.utils import notify_error
class GetAuditLogs(APIView):
def patch(self, request):
from clients.models import Client
from agents.models import Agent
pagination = request.data["pagination"]
order_by = (
f"-{pagination['sortBy']}"
if pagination["descending"]
else f"{pagination['sortBy']}"
)
agentFilter = Q()
clientFilter = Q()
actionFilter = Q()
objectFilter = Q()
userFilter = Q()
timeFilter = Q()
if "agentFilter" in request.data:
agentFilter = Q(agent__in=request.data["agentFilter"])
elif "clientFilter" in request.data:
clients = Client.objects.filter(
pk__in=request.data["clientFilter"]
).values_list("id")
agents = Agent.objects.filter(site__client_id__in=clients).values_list(
"hostname"
)
clientFilter = Q(agent__in=agents)
if "userFilter" in request.data:
userFilter = Q(username__in=request.data["userFilter"])
if "actionFilter" in request.data:
actionFilter = Q(action__in=request.data["actionFilter"])
if "objectFilter" in request.data:
objectFilter = Q(object_type__in=request.data["objectFilter"])
if "timeFilter" in request.data:
timeFilter = Q(
entry_time__lte=djangotime.make_aware(dt.today()),
entry_time__gt=djangotime.make_aware(dt.today())
- djangotime.timedelta(days=request.data["timeFilter"]),
)
audit_logs = (
AuditLog.objects.filter(agentFilter | clientFilter)
.filter(userFilter)
.filter(actionFilter)
.filter(objectFilter)
.filter(timeFilter)
).order_by(order_by)
paginator = Paginator(audit_logs, pagination["rowsPerPage"])
return Response(
{
"audit_logs": AuditLogSerializer(
paginator.get_page(pagination["page"]), many=True
).data,
"total": paginator.count,
}
)
class FilterOptionsAuditLog(APIView):
def post(self, request):
if request.data["type"] == "agent":
agents = Agent.objects.filter(hostname__icontains=request.data["pattern"])
return Response(AgentHostnameSerializer(agents, many=True).data)
if request.data["type"] == "user":
users = User.objects.filter(
username__icontains=request.data["pattern"], agent=None
)
return Response(UserSerializer(users, many=True).data)
return Response("error", status=status.HTTP_400_BAD_REQUEST)
@api_view()
def agent_pending_actions(request, pk):
action = PendingAction.objects.filter(agent__pk=pk)
return Response(PendingActionSerializer(action, many=True).data)
@api_view()
def all_pending_actions(request):
actions = PendingAction.objects.all().select_related("agent")
return Response(PendingActionSerializer(actions, many=True).data)
@api_view(["DELETE"])
def cancel_pending_action(request):
action = get_object_or_404(PendingAction, pk=request.data["pk"])
if not action.agent.has_gotasks:
return notify_error("Requires agent version 1.1.1 or greater")
nats_data = {
"func": "delschedtask",
"schedtaskpayload": {"name": action.details["taskname"]},
}
r = asyncio.run(action.agent.nats_cmd(nats_data, timeout=10))
if r != "ok":
return notify_error(r)
action.delete()
return Response(f"{action.agent.hostname}: {action.description} was cancelled")
@api_view()
def debug_log(request, mode, hostname, order):
log_file = settings.LOG_CONFIG["handlers"][0]["sink"]
agents = Agent.objects.all()
agent_hostnames = AgentHostnameSerializer(agents, many=True)
switch_mode = {
"info": "INFO",
"critical": "CRITICAL",
"error": "ERROR",
"warning": "WARNING",
}
level = switch_mode.get(mode, "INFO")
if hostname == "all" and order == "latest":
cmd = f"grep -h {level} {log_file} | tac"
elif hostname == "all" and order == "oldest":
cmd = f"grep -h {level} {log_file}"
elif hostname != "all" and order == "latest":
cmd = f"grep {hostname} {log_file} | grep -h {level} | tac"
elif hostname != "all" and order == "oldest":
cmd = f"grep {hostname} {log_file} | grep -h {level}"
else:
return Response("error", status=status.HTTP_400_BAD_REQUEST)
contents = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
shell=True,
)
if not contents.stdout:
resp = f"No {mode} logs"
else:
resp = contents.stdout
return Response({"log": resp, "agents": agent_hostnames.data})
@api_view()
def download_log(request):
log_file = settings.LOG_CONFIG["handlers"][0]["sink"]
if settings.DEBUG:
with open(log_file, "rb") as f:
response = HttpResponse(f.read(), content_type="text/plain")
response["Content-Disposition"] = "attachment; filename=debug.log"
return response
else:
response = HttpResponse()
response["Content-Disposition"] = "attachment; filename=debug.log"
response["X-Accel-Redirect"] = "/private/log/debug.log"
return response