From bbbb88b2b2ab86906a116bba2368d72541ebfccc Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 10 Mar 2014 13:15:31 -0400 Subject: [PATCH] Track how many times a user is connected on connect/disconnect events For a log reviewer tool to unambiguously understand whether a given user is conceivably watching, more data is needed. It doesn't keep track of which disconnect goes with which connection, but it at least provides a way of detecting whether user is truly disconnected or not. --- confluent/consoleserver.py | 12 ++++++++++-- confluent/log.py | 17 ++++++++++------- confluent/sockapi.py | 14 +++++++++----- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/confluent/consoleserver.py b/confluent/consoleserver.py index f6c76637..ee42b62c 100644 --- a/confluent/consoleserver.py +++ b/confluent/consoleserver.py @@ -25,6 +25,7 @@ class _ConsoleHandler(object): self.logger = log.Logger(node, tenant=configmanager.tenant) self.buffer = bytearray() self._connect() + self.users = {} def _connect(self): self._console = plugin.handle_path( @@ -58,14 +59,21 @@ class _ConsoleHandler(object): eventlet.spawn(self._handle_console_output, data) def attachuser(self, username): + if username in self.users: + self.users[username] += 1 + else: + self.users[username] = 1 self.logger.log( logdata=username, ltype=log.DataTypes.event, - event=log.Events.clientconnect) + event=log.Events.clientconnect, + eventdata=self.users[username]) def detachuser(self, username): + self.users[username] -= 1 self.logger.log( logdata=username, ltype=log.DataTypes.event, - event=log.Events.clientdisconnect) + event=log.Events.clientdisconnect, + eventdata=self.users[username]) def _handle_console_output(self, data): if type(data) == int: diff --git a/confluent/log.py b/confluent/log.py index ef25a99c..1482d356 100644 --- a/confluent/log.py +++ b/confluent/log.py @@ -45,6 +45,7 @@ # (a future extended version might include suport for Forward Secure Sealing # or other fields) +import collections import confluent.config.configmanager as configuration import eventlet import os @@ -93,14 +94,15 @@ class Logger(object): self.closer = None self.textfile = None self.binfile = None - self.logentries = [] + self.logentries = collections.deque() def writedata(self): if self.textfile is None: self.textfile = open(self.textpath, mode='ab') if self.binfile is None: self.binfile = open(self.binpath, mode='ab') - for entry in self.logentries: + while self.logentries: + entry = self.logentries.popleft() ltype = entry[0] tstamp = entry[1] data = entry[2] @@ -117,8 +119,8 @@ class Logger(object): offset = self.textfile.tell() + len(textdate) datalen = len(data) # metadata length is always 16 for this code at the moment - binrecord = struct.pack(">BBIHII", - 16, ltype, offset, datalen, tstamp, evtdata) + binrecord = struct.pack(">BBIHIBBH", + 16, ltype, offset, datalen, tstamp, evtdata, entry[4], 0) if self.isconsole: if ltype == 2: textrecord = data @@ -128,12 +130,13 @@ class Logger(object): textrecord = textdate + data + '\n' self.textfile.write(textrecord) self.binfile.write(binrecord) - self.logentries = [] + self.textfile.flush() + self.binfile.flush() if self.closer is None: self.closer = eventlet.spawn_after(15, self.closelog) self.writer = None - def log(self, logdata=None, ltype=None, event=0): + def log(self, logdata=None, ltype=None, event=0, eventdata=0): if type(logdata) not in (str, unicode, dict): raise Exception("Unsupported logdata") if ltype is None: @@ -152,7 +155,7 @@ class Logger(object): self.logentries[-1][1] == timestamp): self.logentries[-1][2] += logdata else: - self.logentries.append([ltype, timestamp, logdata, event]) + self.logentries.append([ltype, timestamp, logdata, event, eventdata]) if self.writer is None: self.writer = eventlet.spawn_after(2, self.writedata) diff --git a/confluent/sockapi.py b/confluent/sockapi.py index 31e53df7..068931ec 100644 --- a/confluent/sockapi.py +++ b/confluent/sockapi.py @@ -42,13 +42,12 @@ class ClientConsole(object): self.pendingdata = None -def sessionhdl(connection, authname): +def sessionhdl(connection, authname, skipauth): # For now, trying to test the console stuff, so let's just do n4. authenticated = False authdata = None - if authname and isinstance(authname, bool): + if skipauth: authenticated = True - authname = "superuser" cfm = configmanager.ConfigManager(tenant=None) elif authname: authdata = auth.authorize(authname, element=None) @@ -170,19 +169,24 @@ def _unixdomainhandler(): creds = cnn.getsockopt(socket.SOL_SOCKET, SO_PEERCRED, struct.calcsize('3i')) pid, uid, gid = struct.unpack('3i',creds) + skipauth = False if uid in (os.getuid(), 0): #this is where we happily accept the person #to do whatever. This allows the server to #start with no configuration whatsoever #and yet still be configurable by some means - authname = True + skipauth = True + try: + authname = pwd.getpwuid(uid).pw_name + except: + authname = "UNKNOWN SUPERUSER" else: try: authname = pwd.getpwuid(uid).pw_name except KeyError: cnn.close() return - eventlet.spawn_n(sessionhdl, cnn, authname) + eventlet.spawn_n(sessionhdl, cnn, authname, skipauth)