+
+
+@csrf_exempt
+def ssh_keys_seen(request):
+ key = request.GET.get('key')
+ service = get_object_or_404(Service, key=key)
+ n = now()
+
+ 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:]+)$'
+
+ last_seen = {}
+ for line in request.body.decode('latin1').split('\n'):
+ if not line.strip():
+ continue
+ data = parse_log_line(line)
+ if data is None:
+ continue
+ dt = data['datetime']
+ algo = data['algo']
+ if 'md5' in data:
+ hash_type = 'md5'
+ hash_value = data['md5']
+ else:
+ hash_type = 'sha256'
+ hash_value = data['sha256']
+ key = algo, hash_type, hash_value
+ last_seen[key] = max(last_seen.get(key, dt), dt)
+
+ for key, dt in last_seen.items():
+ algo, hash_type, hash_value = key
+ SSHKey.objects.filter(
+ Q(last_seen_at=None) | Q(last_seen_at__lt=dt),
+ algorithm=algo,
+ **{f'{hash_type}_hash': hash_value}
+ ).update(
+ last_seen_at=dt
+ )
+
+ return http.HttpResponse('ok')
+