1 from datetime import datetime, timedelta
4 from django.contrib.auth.mixins import LoginRequiredMixin
5 from django.contrib import messages
6 from django.db import IntegrityError
7 from django.db.models import Q
8 from django import http
9 from django.shortcuts import get_object_or_404
10 from django.utils.timezone import now
11 from django.utils.translation import ugettext as _
12 from django.views.decorators.csrf import csrf_exempt
13 from django.views.generic import ListView, CreateView, DeleteView
14 from services.models import Service
15 from .models import SSHKey
16 from .utils import parse_log_line
19 class SSHKeysView(LoginRequiredMixin, ListView):
20 def get_queryset(self):
21 return SSHKey.objects.filter(user=self.request.user)
24 class AddSSHKeyView(LoginRequiredMixin, CreateView):
28 template_name = 'ssh_keys/sshkey_add.html'
30 def form_valid(self, form):
31 form.instance.user = self.request.user
33 return super().form_valid(form)
34 except ValueError as e:
35 messages.add_message(self.request, messages.ERROR, e)
36 except IntegrityError:
37 messages.add_message(self.request, messages.ERROR, _("Key already in the database."))
38 return http.HttpResponseRedirect(self.success_url)
42 class DeleteSSHKeyView(LoginRequiredMixin, DeleteView):
45 def get_queryset(self):
46 return SSHKey.objects.filter(user=self.request.user)
50 def ssh_keys_seen(request):
51 logger = logging.getLogger('django.request')
52 key = request.GET.get('key')
53 service = get_object_or_404(Service, key=key)
56 logline_re = r'^(?P<time>\w{3}\s+\d+\s+\d\d:\d\d:\d\d).*: Accepted publickey for .* from .* port .* ssh2: (?P<algo>\w+) (?P<hash>[a-f0-9:]+)$'
59 for line in request.body.decode('latin1').split('\n'):
62 data = parse_log_line(line)
64 logger.error('Unparsed: ' + line)
70 hash_value = data['md5']
73 hash_value = data['sha256']
74 key = algo, hash_type, hash_value
75 last_seen[key] = max(last_seen.get(key, dt), dt)
77 for key, dt in last_seen.items():
78 algo, hash_type, hash_value = key
79 SSHKey.objects.filter(
80 Q(last_seen_at=None) | Q(last_seen_at__lt=dt),
82 **{f'{hash_type}_hash': hash_value}
87 return http.HttpResponse('ok')