[Oval-commits] r369 - trunk/oval-monitor

Pavel Vinogradov blaze-guest at alioth.debian.org
Sun Sep 14 15:54:55 UTC 2008


Author: blaze-guest
Date: 2008-09-14 15:54:55 +0000 (Sun, 14 Sep 2008)
New Revision: 369

Added:
   trunk/oval-monitor/db.py
   trunk/oval-monitor/dba.py
   trunk/oval-monitor/manager.py
   trunk/oval-monitor/oval-server.db
Log:
Initial source import


Added: trunk/oval-monitor/db.py
===================================================================
--- trunk/oval-monitor/db.py	                        (rev 0)
+++ trunk/oval-monitor/db.py	2008-09-14 15:54:55 UTC (rev 369)
@@ -0,0 +1,211 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#                                                                                                   # Written by Pavel Vinogradov
+# Licensed under the GNU General Public License version 2.
+
+from ConfigParser import SafeConfigParser
+from dba import dba, dbaNotAccesible
+import os, sys, time, getopt
+import traceback, exceptions
+sys.path = ['/usr/share/oval-server'] + sys.path
+
+assert sys.version_info >= (2,4), 'Requires Python 2.4 or better'
+
+class configNotFoundError (Exception):
+    pass
+
+def usage (prog = 'oval-monitor.py'):
+    """Print information about script flags and options"""
+
+    print """usage: python %s [-h] [-c <config>] [-a <agent ip>] [-d <dsa id>]
+\t-h\tthis help
+\t-c\tpath to config file (by default /etc/oval/server.conf
+\t-a\tagent id
+\t-d\tDebian Security Annnounce id
+""" % prog
+
+class Report:
+    
+    config = SafeConfigParser()
+
+    def __init__(self, cfgfile):
+        try:
+            # Read global server config
+            if not self.config.read(cfgfile):
+                raise configNotFoundError, 'Config file %s not found.\n' % cfgfile 
+
+            self.dbPath = self.config.get ('general', 'db')
+            #Init static fields in dba and Dsa2Oval classes
+            dba.dbPath = "/tmp/oval-server.db"#self.dbPath
+            self.db = dba ()
+        except Exception, e:
+            raise e
+
+    def getAgentAffectedVuln (self, agentID):
+        """ Return list of affected DSA for certain agent
+
+        Return list of DSA numbers which affected host for certain agent.
+
+        @type agentID: C(integer)
+        @param agentID: Identificator of inspected agent
+        @rtype: C(list)
+        @return: list of DSA numbers
+        """
+
+        cursor = self.db.getCursor()
+
+        cursor.execute ('SELECT vulnDSA from affected WHERE agentID = %d and status = 1' % agentID)
+        result = cursor.fetchall()
+        return result
+
+    def getAgentNottestedVuln (self, agentID):
+        """ Return list of not tested DSA for certain agent
+
+        Return list of DSA numbers which not tested again host for certain agent.
+
+        @type agentID: C(integer)
+        @param agentID: Identificator of inspected agent
+        @rtype: C(list)
+        @return: list of DSA numbers
+        """
+
+        cursor = self.db.getCursor()
+        
+        cursor.execute ("""SELECT vulnDSA FROM vulnerabilities 
+            WHERE vulnDSA NOT IN (
+                SELECT vulnDSA FROM affected where agentID = %d);
+                """ % agentID)
+        result = cursor.fetchall()
+        return result
+
+    def reportAgent (self, agentID):
+        """Generate report for certain agent.
+
+        Generate report, which include list of affected and not tested DSA.
+        Also contain number of not affected DSA.
+
+        @type agentID: C(integer)
+        @param agentID: Identificator of inspected agent
+        """
+
+        cursor = self.db.getCursor()
+
+        cursor.execute ('SELECT vulnDSA, status from affected WHERE agentID = %d' % agentID)
+        dsas = cursor.fetchall()
+        count = 0
+
+        print 'Agent %d:' % agentID
+        for dsa in dsas:
+            if dsa[1] == 1:
+                print '\tAffected to DSA ID %s' % dsa[0]
+            else:
+                count += 1
+        print '\tNot affected to %d DSA' % count
+
+        print '--------------------------'
+        cursor.execute ("""SELECT vulnerabilities.vulnDSA FROM vulnerabilities 
+            OUTER JOIN affected
+            ON vulnerabilities.vulnDSA = affected.vulnDSA
+            WHERE affected.agentID = %d AND vulnerabilities.vulnTimestamp > affected.vulnTimestamp OR affected.vulnTimestamp IS NULL;""" % agentID)
+
+        dsas = cursor.fetchall()
+        count = 0
+        for dsa in dsas:
+            print 'Not tested again DSA ID %s' %dsa[0]
+            count += 1    
+            
+    def reportDSA (self, dsaID):
+        """Generate report for certain DSA.
+
+        Generate report, which include list of affected and not tested agents 
+        again certain DSA.
+
+        @type agentID: C(integer)
+        @param agentID: Identificator of inspected DSA
+        """
+        
+        cursor = self.db.getCursor()
+        cursor.execute ('SELECT affected.agentID, agents.agentName from affected JOIN agents on affected.agentID = agents.agentID WHERE vulnDSA = %d and status = 1' % dsaID)
+        agents = cursor.fetchall ()
+        print 'Agents affected to DSA %d:' % dsaID
+        for agent in agents:
+            print '\t%d \t %s' % (agent[0], agent[1])
+
+        print '------------------------------'
+        cursor.execute ("""
+            SELECT agentID, agentName from agents 
+                WHERE agentID NOT IN (
+                    SELECT agentID FROM affected WHERE vulnDSA = %d);""" % dsaID)
+        agents = cursor.fetchall ()
+        print 'Agents not tested to DSA %d:' % dsaID
+        for agent in agents:
+            print '\t%d \t %s' % (agent[0], agent[1])    
+
+    def reportFull (self):
+        """Generate full report about status of all agents.
+
+        Generate report, which include list of all registered agents with:
+        ID, IP, number of affected and not tested DSA.
+        """
+        result = ""
+        
+        cursor = self.db.getCursor()
+
+        cursor.execute ("SELECT * FROM agents;")
+        agents = cursor.fetchall()
+
+        result += 'Agents: (ID \t IP \t\t Aff \tNot tested)\n'
+        for agent in agents:
+            result += '\t %d \t %s \t %s \t %s\n' % (agent[0], agent[1], len(self.getAgentAffectedVuln(agent[0])), len(self.getAgentNottestedVuln(agent[0])))
+    
+        cursor.execute ("SELECT count(*) from vulnerabilities;")
+        dsas = cursor.fetchall()[0][0]
+        result += 'DSA in repository: %d\n' % dsas
+        
+        return result
+
+if __name__ == "__main__":
+    #Parse command line options. 
+    #By default we search for config file in global etc directory 
+    opts = {'-c' : '/etc/oval/server.conf'}
+    
+    try:
+        opt, args = getopt.getopt (sys.argv[1:], 'hc:a:d:')
+    except getopt.GetoptError:
+        usage (sys.argv[0])
+        sys.exit(1)
+    
+    for key, value in opt: 
+        opts[key] = value
+
+    if opts.has_key ('-h'):
+        usage(sys.argv[0])
+        sys.exit(0)
+
+    try:
+        reporter = Report (opts['-c'])
+    
+        if opts.has_key ('-a'):
+            try:
+                reporter.reportAgent (int(opts['-a']))
+            except ValueError:
+                print 'Please enter numeric agent ID'
+        else:
+            if opts.has_key ('-d'):
+                try:
+                    reporter.reportDSA (int(opts['-d']))
+                except ValueError:
+                    print 'Please enter numeric DSA id'
+            else:
+                reporter.reportFull ()
+    
+    except configNotFoundError, e:
+        sys.stderr.write (str(e))
+    except dbaNotAccesible, e:
+        sys.stderr.write ("ERROR: Can't access to database file\n")
+        usage(sys.argv[0])
+    except exceptions.SystemExit, e:
+        raise e
+    except Exception, e:
+        sys.stderr.write('ERROR: Unhandled error during execution: %s : %s.\n' % (e.__class__, str(e)))
+        traceback.print_exc()
\ No newline at end of file

Added: trunk/oval-monitor/dba.py
===================================================================
--- trunk/oval-monitor/dba.py	                        (rev 0)
+++ trunk/oval-monitor/dba.py	2008-09-14 15:54:55 UTC (rev 369)
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+# 
+# Written by Pavel Vinogradov <Pavel.Vinogradov at nixdev.net>
+# Licensed under the GNU General Public License version 2.
+
+from pysqlite2 import dbapi2 as db
+from datetime import datetime
+
+class dbaNotInitialized(Exception):
+	pass
+
+class AgentAlreadyExistException(Exception):
+	pass
+
+class AgentDoesNotExistException(Exception):
+	pass
+
+class dbaNotAccesible (Exception):
+	pass
+
+class dba:
+	"""
+		You need initialize static field dbPath before create instances of dba class"""
+		
+	__dbStruct = """		
+		drop table if exists agents;
+		create table agents(
+				agentID INTEGER primary key AUTOINCREMENT,
+				agentName varchar(255),
+				agentStatus smallint DEFAULT 0,
+				agentTimestamp datetime DEFAULT CURRENT_TIMESTAMP
+		);
+		
+		drop table if exists vulnerabilities;
+		create table vulnerabilities(
+				vulnID INTEGER primary key AUTOINCREMENT,
+				vulnDSA INTEGER,
+				vulnLocation carchar(255),
+				vulnTimestamp datetime
+		);
+
+		drop table if exists affected;
+		create table affected(
+				id INTEGER primary key AUTOINCREMENT,
+				agentID INTEGER,
+				vulnDSA INTEGER,
+				vulnTimestamp datetime,
+				status smallint
+		);"""
+	
+	dbPath = None
+	
+	def __init__ (self):
+		if dba.dbPath == None:
+			raise dbaNotInitialized
+				
+		try:
+			self.__conn = db.connect(self.dbPath)
+			self.__conn.isolation_level = None
+			self.cursor = self.__conn.cursor()
+			#Chech if tables exists
+			self.cursor.execute ("""SELECT name FROM sqlite_master 
+				WHERE type=\'table\'
+				ORDER BY name;""")
+			if not self.cursor.fetchall():
+				raise dbaNotInitialized ()
+		except dbaNotInitialized:
+			self.__initDB()
+		except db.OperationalError:
+			raise dbaNotAccesible
+
+		
+	def getCursor(self):
+		if self.__conn:
+			if self.cursor:
+				return self.cursor
+			else:
+				self.cursor = self.__conn.cursor()
+	
+	def __initDB(self):
+		self.cursor.executescript(self.__dbStruct)
+
+	def updateAffected(self, agentID, vulnID, status):
+		self.cursor.execute ('SELECT id FROM affected WHERE agentID = %d AND vulnDSA = %d' % 
+							(agentID, vulnID))
+		timestamp = datetime.now().strftime('%Y-%m-%d %H:%M')	
+		try:
+			id = self.cursor.fetchall()[0][0]
+			self.cursor.execute ('UPDATE  affected set  status = %d, vulnTimestamp = \'%s\' WHERE id = %d' % (status, timestamp, id))
+		except IndexError:
+			self.cursor.execute ('INSERT INTO affected VALUES (NULL, %d, %d, \'%s\', %d)' %
+				(agentID, vulnID, timestamp, status))
+			
+	def updateDSA(self, dsa, location, timestamp):
+		self.cursor.execute ('SELECT vulnID FROM vulnerabilities WHERE vulnDSA = %d' % dsa)
+		if self.cursor.fetchall():
+			self.cursor.execute ('UPDATE  vulnerabilities set  vulnLocation = \'%s\', vulnTimestamp = \'%s\' WHERE vulnDSA = %d' % (location, timestamp, dsa))
+		else:
+			self.__insertDSA(dsa, location, timestamp)
+				
+	def __insertDSA(self, dsa, location, timestamp):
+		self.cursor.execute ('INSERT  INTO vulnerabilities (vulnDSA, vulnLocation, vulnTimestamp) VALUES (%d, \'%s\', \'%s\')' % (dsa, location, timestamp))
+		
+	def addAgent(self, agentName):
+		self.cursor.execute ('SELECT agentID FROM agents WHERE agentName = \'%s\'' % agentName)
+		if self.cursor.fetchall():
+			raise AgentAlreadyExistException
+		else:
+			self.cursor.execute ('INSERT INTO agents (agentID, agentName, agentTimestamp) VALUES (NULL, \'%s\', \'%s\')' %
+								(agentName, datetime.now().strftime('%Y-%m-%d %H:%M')))
+	
+	def getAgentInfo(self, agentName):
+		self.cursor.execute ('SELECT agentID FROM agents WHERE agentName = \'%s\'' % agentName)
+		try:
+			agentID = self.cursor.fetchall()[0][0]
+			return agentID
+		except IndexError:
+			return 0
+	
+	def getAgentsList(self):
+		self.cursor.execute ('SELECT agentID, agentName FROM agents')
+		return self.cursor.fetchall()
+		
+	def makeDefList (self, agentID):
+		self.cursor.execute (
+				"""SELECT vulnLocation FROM vulnerabilities 
+					LEFT JOIN affected 
+					ON vulnerabilities.vulnDSA = affected.vulnDSA 
+					WHERE affected.agentID = %d AND vulnerabilities.vulnTimestamp > affected.vulnTimestamp OR affected.vulnTimestamp IS NULL OR affected.status = 1;
+			""" % agentID)
+		return self.cursor.fetchall()
+		
+if __name__ == "__main__":
+	dba.dbPath ='/home/blaze/tmp/oval/server/oval-server.db' 
+	sql = dba()
+	print sql.makeDefList(1)

Added: trunk/oval-monitor/manager.py
===================================================================
--- trunk/oval-monitor/manager.py	                        (rev 0)
+++ trunk/oval-monitor/manager.py	2008-09-14 15:54:55 UTC (rev 369)
@@ -0,0 +1,107 @@
+import wx
+import os
+
+from db import Report
+
+ID_ABOUT=wx.NewId()
+ID_OPEN=wx.NewId()
+ID_PREFERENCES=wx.NewId()
+ID_BUTTON1=wx.NewId()
+ID_EXIT=wx.NewId()
+
+class MainWindow(wx.Frame):
+    def __init__(self,parent,id,title):
+        #self.dirname=''
+        wx.Frame.__init__(self, parent, wx.ID_ANY, title, pos=(150, 150), size=(350, 200))
+        self.control = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE)
+      
+        # Setting statusbar
+        self.CreateStatusBar() # A Statusbar in the bottom of the window
+        
+        # Setting up the filemenu.
+        filemenu=wx.Menu()
+        #filemenu.Append(ID_OPEN, "&Open"," Open a file to edit")
+        filemenu.AppendSeparator()
+        filemenu.Append(ID_EXIT,"E&xit"," Terminate the program")
+        
+        # Setting up the aboutmenu.
+        aboutmenu=wx.Menu()
+        aboutmenu.Append(ID_ABOUT, "&About"," Information about this program")
+        
+        # Setting up the settingsmenu.
+        settingsmenu=wx.Menu()
+        settingsmenu.Append(ID_PREFERENCES, "&Preferences"," OVAL monitor preferences ")
+        
+        # Creating the menubar.
+        menuBar = wx.MenuBar()
+        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
+        menuBar.Append(settingsmenu,"&Settings") # Adding the "settingsmenu" to the MenuBar
+        menuBar.Append(aboutmenu,"&Help") # Adding the "aboutmenu" to the MenuBar        
+        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
+        
+        wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
+        wx.EVT_MENU(self, ID_EXIT, self.OnExit)
+        #wx.EVT_MENU(self, ID_OPEN, self.OnOpen)
+        
+        self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
+        self.tabs=[]
+        self.tabs.append(wx.Button(self, wx.NewId(), "Current status"))
+        self.tabs.append(wx.Button(self, wx.NewId(), "Statistic"))
+        for i in range(len(self.tabs)):            
+            self.sizer2.Add(self.tabs[i],1,wx.EXPAND)
+            wx.EVT_BUTTON(self, self.tabs[i].GetId(), self.OnClick)
+        
+        # Use some sizers to see layout options
+        self.sizer=wx.BoxSizer(wx.VERTICAL)
+        self.sizer.Add(self.sizer2,0,wx.EXPAND)
+        self.sizer.Add(self.control,1,wx.EXPAND)
+                
+        #Layout sizers
+        self.SetSizer(self.sizer)
+        self.SetAutoLayout(1)
+        self.sizer.Fit(self)
+        self.Show(1)
+        
+    def OnAbout(self,e):
+        d= wx.MessageDialog( self, " OVAL status monitor \n"
+                            " alpha version","OVAL monitor", wx.OK)
+        d.ShowModal() # Shows it
+        d.Destroy() # finally destroy it when finished.
+
+    def OnExit(self,e):
+        self.Close(True)  # Close the frame.
+
+#    def OnOpen(self,e):
+#        """ Open a file"""
+#        dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
+#        if dlg.ShowModal() == wx.ID_OK:
+#            self.filename=dlg.GetFilename()
+#            self.dirname=dlg.GetDirectory()
+#            f=open(os.path.join(self.dirname, self.filename),'r')
+#            self.control.SetValue(f.read())
+#            f.close()
+#        dlg.Destroy()
+
+    def OnClick(self,event):
+        result = " Click on object with Id %d\n" %event.GetId() 
+        try:
+            reporter = Report ("/etc/oval/server.conf")
+            result = reporter.reportFull ()
+        
+        except configNotFoundError, e:
+            sys.stderr.write (str(e))
+        except dbaNotAccesible, e:
+            sys.stderr.write ("ERROR: Can't access to database file\n")
+            usage(sys.argv[0])
+        except exceptions.SystemExit, e:
+            raise e
+        except Exception, e:
+            sys.stderr.write('ERROR: Unhandled error during execution: %s : %s.\n' % (e.__class__, str(e)))
+            traceback.print_exc()
+        
+        self.control.AppendText(result)
+
+if __name__ == "__main__":
+    app = wx.PySimpleApp()
+    frame = MainWindow(None, -1, "OVAL status monitor")
+    app.MainLoop()
\ No newline at end of file

Added: trunk/oval-monitor/oval-server.db
===================================================================
(Binary files differ)


Property changes on: trunk/oval-monitor/oval-server.db
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream




More information about the Oval-commits mailing list