[Oval-commits] r382 - trunk/oval-infrastructure/src
Pavel Vinogradov
blaze-guest at alioth.debian.org
Tue Sep 23 17:41:39 UTC 2008
Author: blaze-guest
Date: 2008-09-23 17:41:39 +0000 (Tue, 23 Sep 2008)
New Revision: 382
Added:
trunk/oval-infrastructure/src/dba.py
trunk/oval-infrastructure/src/manager.py
trunk/oval-infrastructure/src/oval-server.db
trunk/oval-infrastructure/src/reporter.py
Log:
Merge oval-monitor
Copied: trunk/oval-infrastructure/src/dba.py (from rev 379, trunk/oval-monitor/dba.py)
===================================================================
--- trunk/oval-infrastructure/src/dba.py (rev 0)
+++ trunk/oval-infrastructure/src/dba.py 2008-09-23 17:41:39 UTC (rev 382)
@@ -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)
Property changes on: trunk/oval-infrastructure/src/dba.py
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/oval-infrastructure/src/manager.py (from rev 379, trunk/oval-monitor/manager.py)
===================================================================
--- trunk/oval-infrastructure/src/manager.py (rev 0)
+++ trunk/oval-infrastructure/src/manager.py 2008-09-23 17:41:39 UTC (rev 382)
@@ -0,0 +1,303 @@
+import wx
+import wx.grid
+import os
+import sys
+import traceback
+from reporter import Report
+
+ID_ABOUT=wx.NewId()
+ID_REFRESH=wx.NewId()
+ID_PREFERENCES=wx.NewId()
+ID_BUTTON1=wx.NewId()
+ID_EXIT=wx.NewId()
+
+class AgentsGridTable(wx.grid.PyGridTableBase):
+
+ cols = ["ID", "IP", "Affected", "Not Affected", "Not Tested"]
+
+ def __init__(self, reporter):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.reporter = reporter
+ self.data = self.reporter.reportGeneral()
+
+ def Update(self):
+ self.data = self.reporter.reportGeneral()
+
+ def GetNumberRows(self):
+ """Return the number of rows in the grid"""
+ return len(self.data)
+
+ def GetNumberCols(self):
+ """Return the number of columns in the grid"""
+ return len(AgentsGridTable.cols)
+
+ def IsEmptyCell(self, row, col):
+ """Return True if the cell is empty"""
+ return False
+
+ def GetTypeName(self, row, col):
+ """Return the name of the data type of the value in the cell"""
+ return None
+
+ def GetValue(self, row, col):
+ """Return the value of a cell"""
+ return self.data[row][col]
+
+ def SetValue(self, row, col, value):
+ """Set the value of a cell"""
+ pass
+
+ def GetColLabelValue(self, col):
+ return self.cols[col]
+
+class MonitorConfig():
+
+ def __init__(self):
+ self._readConf()
+
+ def _readConf(self):
+ self.cfg = wx.Config('monitor')
+ if self.cfg.Exists('AutoRefresh'):
+ self.refrAuto = self.cfg.ReadBool('AutoRefresh');
+ else:
+ self.refrAuto = True
+
+ if self.cfg.Exists('RefreshRate'):
+ self.refrRate = self.cfg.ReadInt('RefreshRate');
+ else:
+ self.refrRate = 10
+
+ if self.cfg.Exists('DbPath'):
+ self.dbPath = self.cfg.Read('DbPath');
+ else:
+ self.dbPath = "./oval-server.db"
+
+ def updateConf(self, auto, rate, path):
+ self.refrAuto = auto
+ self.refrRate = rate
+ self.dbPath = path
+ self.writeConf()
+
+ def writeConf(self):
+ self.cfg.WriteBool("AutoRefresh", self.refrAuto)
+ self.cfg.WriteInt("RefreshRate", self.refrRate)
+ self.cfg.Write("DbPath", self.dbPath)
+
+class MonitorPrefBox(wx.Dialog):
+ def __init__(self, parent, id, title):
+ wx.Dialog.__init__(self, parent, id, title, size=(360, 190))
+
+ self.conf = MonitorConfig()
+ wx.StaticBox(self, -1, 'Settings', (5, 5), size=(340, 120))
+
+ self.cb = wx.CheckBox(self, -1 ,'Auto-refresh', (15, 30))
+ self.cb.SetValue(self.conf.refrAuto)
+
+ wx.EVT_CHECKBOX(self, self.cb.GetId(), self.OnToggleRateSpin)
+
+ wx.StaticText(self, -1, 'Refresh rate', (30, 55))
+ self.sp = wx.SpinCtrl(self, -1, str(self.conf.refrRate), (105, 55), (50, -1), min=1, max=120)
+
+ wx.StaticText(self, -1, 'Path to db', (15, 95))
+ self.tc = wx.TextCtrl(self, -1, self.conf.dbPath, size=(230, 25), pos=(100, 85))
+
+ wx.Button(self, 1, 'Ok', (150, 130), (60, -1))
+
+ self.Bind(wx.EVT_BUTTON, self.OnClose, id=1)
+
+ self.Centre()
+ self.ShowModal()
+ self.Destroy()
+
+
+ def OnToggleRateSpin(self, event):
+ if self.sp.IsEnabled():
+ self.sp.Disable()
+ else:
+ self.sp.Enable()
+
+ def OnClose(self, event):
+ self.conf.updateConf(self.cb.GetValue(), self.sp.GetValue(), self.tc.GetValue())
+ self.Close()
+
+class AgentPopupMenu(wx.Menu):
+ def __init__(self, parent):
+ wx.Menu.__init__(self)
+
+ self.parent = parent
+
+ query = wx.MenuItem(self, wx.NewId(), 'Query')
+ self.AppendItem(query)
+ self.Bind(wx.EVT_MENU, self.OnQuery, id=query.GetId())
+
+ detail = wx.MenuItem(self, wx.NewId(), 'Detail')
+ self.AppendItem(detail)
+ self.Bind(wx.EVT_MENU, self.OnDetail, id=detail.GetId())
+
+
+ def OnQuery(self, event):
+ pass
+
+ def OnDetail(self, event):
+ pass
+
+class MainWindow(wx.Frame):
+ def __init__(self,parent,id,title):
+
+ wx.Frame.__init__(self, parent, wx.ID_ANY, title, pos=(150, 150), size=(350, 200))
+
+ self.conf = MonitorConfig()
+ self.grid = self.__initGrid()
+ self.log = wx.TextCtrl(self, 1, size=(10, 10), style=wx.TE_AUTO_SCROLL | wx.TE_READONLY | wx.TE_AUTO_URL | wx.TE_MULTILINE)
+
+ # A Statusbar in the bottom of the window
+ self.CreateStatusBar()
+ # Adding the MenuBar to the Frame content.
+ self.SetMenuBar(self.__createMenu())
+
+ wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
+ wx.EVT_MENU(self, ID_REFRESH, self.OnRefresh)
+ wx.EVT_MENU(self, ID_EXIT, self.OnExit)
+ wx.EVT_MENU(self, ID_PREFERENCES, self.OnPref)
+
+# self.sizerButtons = wx.BoxSizer(wx.HORIZONTAL)
+# self.tabs=[]
+# statusButton = wx.Button(self, wx.NewId(), "Current status")
+# statisticButton = wx.Button(self, wx.NewId(), "Statistic")
+# wx.EVT_BUTTON(self, statusButton.GetId(), self.OnStatus)
+# wx.EVT_BUTTON(self, statisticButton.GetId(), self.OnStatistic)
+
+# self.tabs.append(statusButton)
+# self.tabs.append(statisticButton)
+# for i in range(len(self.tabs)):
+# self.sizerButtons.Add(self.tabs[i],1,wx.EXPAND)
+
+ self.sizerGrid = wx.BoxSizer(wx.HORIZONTAL)
+ self.sizerGrid.Add(self.grid, 1, wx.EXPAND)
+
+ # Use some sizers to see layout options
+ self.sizer=wx.BoxSizer(wx.VERTICAL)
+# self.sizer.Add(self.sizerButtons,0,wx.EXPAND)
+ self.sizer.Add(self.sizerGrid,1,wx.EXPAND)
+ self.sizer.Add(self.log,2,wx.EXPAND)
+
+ #Layout sizers
+ self.SetSizer(self.sizer)
+ self.SetAutoLayout(1)
+ self.sizer.Fit(self)
+ self.Show(1)
+
+ def __createMenu(self):
+ # Setting up the filemenu.
+ menuFile=wx.Menu()
+ menuFile.AppendSeparator()
+ menuFile.Append(ID_EXIT,"E&xit"," Terminate the program")
+
+ # Setting up the actions menu
+ menuActions=wx.Menu()
+ menuActions.Append(ID_REFRESH, "&Refresh"," Refresh Agents info ")
+
+ # Setting up the settingsmenu.
+ menuSettings=wx.Menu()
+ menuSettings.Append(ID_PREFERENCES, "&Preferences"," OVAL monitor preferences ")
+
+ # Setting up the aboutmenu.
+ menuAbout=wx.Menu()
+ menuAbout.Append(ID_ABOUT, "&About"," Information about this program")
+
+ # Creating the menubar.
+ menuBar = wx.MenuBar()
+ menuBar.Append(menuFile,"&File") # Adding the "filemenu" to the MenuBar
+ menuBar.Append(menuActions, "Actions")
+ menuBar.Append(menuSettings,"&Settings") # Adding the "settingsmenu" to the MenuBar
+ menuBar.Append(menuAbout,"&Help") # Adding the "aboutmenu" to the MenuBar
+
+ return menuBar
+
+ def __initGrid(self):
+ newGrid = wx.grid.Grid(self)
+ table = AgentsGridTable(Report (self.conf.dbPath))
+ newGrid.SetTable(table, True)
+ self.table = table
+ wx.grid.EVT_GRID_CELL_LEFT_DCLICK(self, self.OnStatus)
+ wx.grid.EVT_GRID_CELL_RIGHT_CLICK(self, self.OnAgentContext)
+
+ return newGrid
+
+ def __updateGrid(self):
+ self.log.AppendText("Updating agent grid\n")
+ self.table.Update()
+ self.grid.Refresh()
+
+ def __appendLog(self, message):
+ self.log.AppendText(message)
+
+ def OnAbout(self,e):
+ description = """Oval Monitor is an advanced GUI tool for monitoring status of Oval agents.
+Features include agents list, full network status, detailed agent status, manual agent control
+and much more."""
+
+ licence = """File Hunter is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+
+File Hunter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details. You should have received a copy of
+the GNU General Public License along with File Hunter; if not, write to
+the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"""
+
+ info = wx.AboutDialogInfo()
+
+ #info.SetIcon(wx.Icon('icons/hunter.png', wx.BITMAP_TYPE_PNG))
+ info.SetName('Oval Monitor')
+ info.SetVersion('0.1.0')
+ info.SetDescription(description)
+ info.SetCopyright('(C) 2008 Pavel Vinogradov')
+ info.SetWebSite('http://www.nixdev.net')
+ info.SetLicence(licence)
+ info.AddDeveloper('Pavel Vinogradov')
+ info.AddDeveloper('Javier Fernandez-Sanguino')
+ wx.AboutBox(info)
+
+ def OnRefresh(self, e):
+ self.__updateGrid()
+
+ def OnPref(self, e):
+ MonitorPrefBox(self, wx.NewId(), 'Monitor preference')
+
+ def OnExit(self,e):
+ self.Close(True) # Close the frame.
+
+# def addRow(self):
+# msg = wx.grid.GridTableMessage(self.table, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, 1)
+# self.grid.ProcessTableMessage(msg)
+# self.grid.ForceRefresh()
+#
+# def delRow(self):
+# msg = wx.grid.GridTableMessage(self.table, wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, self.grid.GetNumberRows(), 1)
+# self.grid.ProcessTableMessage(msg)
+# self.grid.ForceRefresh()
+
+ def OnAgentContext(self, event):
+ self.PopupMenu(AgentPopupMenu(self), event.GetPosition())
+ self.__appendLog(str(event))
+
+ def OnStatus(self, event):
+ self.grid.Show()
+# result = " Click on object with Id %d\n" %event.GetId()
+# #self.delRow()
+# self.__appendLog(result)
+# self.__appendLog(Report (self.conf.dbPath).reportStdAgent(event.Row+1))
+ self.__updateGrid()
+
+ def OnStatistic(self, event):
+ self.grid.Hide()
+# result = " Click on object with Id %d\n" %event.GetId()
+# #self.addRow()
+# self.__appendLog(result)
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MainWindow(None, -1, "OVAL status monitor")
+ app.MainLoop()
\ No newline at end of file
Property changes on: trunk/oval-infrastructure/src/manager.py
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/oval-infrastructure/src/oval-server.db (from rev 379, trunk/oval-monitor/oval-server.db)
===================================================================
(Binary files differ)
Property changes on: trunk/oval-infrastructure/src/oval-server.db
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Name: svn:mergeinfo
+
Copied: trunk/oval-infrastructure/src/reporter.py (from rev 379, trunk/oval-monitor/reporter.py)
===================================================================
--- trunk/oval-infrastructure/src/reporter.py (rev 0)
+++ trunk/oval-infrastructure/src/reporter.py 2008-09-23 17:41:39 UTC (rev 382)
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# # Written by Pavel Vinogradov
+# Licensed under the GNU General Public License version 2.
+
+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 Report:
+
+ def __init__(self, dbfile):
+ dba.dbPath = dbfile
+ self.db = dba ()
+
+ 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 __getAgentNotAffectedVuln (self, agentID):
+ """ Return list of not affected DSA for certain agent
+
+ Return list of DSA numbers which not 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 = 0' % 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 reportGeneral (self):
+ """Generate full report about status of all agents.
+
+ Generate report, which include list of all registered agents with:
+ ID, IP, number of affected, not affected and not tested DSA.
+ """
+ result = []
+
+ cursor = self.db.getCursor()
+
+ cursor.execute ("SELECT * FROM agents;")
+ agents = cursor.fetchall()
+
+ for agent in agents:
+ #ID, IP, AFF, NotAFF, NotTested
+ result.append([agent[0], agent[1], len(self.__getAgentAffectedVuln(agent[0])), len(self.__getAgentNotAffectedVuln (agent[0])), len(self.__getAgentNotTestedVuln (agent[0]))])
+
+ 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 reportStdAgent (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
+ """
+ result = ""
+ cursor = self.db.getCursor()
+
+ cursor.execute ('SELECT vulnDSA, status from affected WHERE agentID = %d' % agentID)
+ dsas = cursor.fetchall()
+ count = 0
+
+ result += 'Agent %d:\n' % agentID
+ for dsa in dsas:
+ if dsa[1] == 1:
+ result += '\tAffected to DSA ID %s\n' % dsa[0]
+ else:
+ count += 1
+ result += '\tNot affected to %d DSA\n' % count
+
+ result += '--------------------------\n'
+ 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:
+ result += 'Not tested again DSA ID %s\n' %dsa[0]
+ count += 1
+
+ return result
\ No newline at end of file
More information about the Oval-commits
mailing list