[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