Skip to content
Snippets Groups Projects
Commit 84c23d84 authored by Michal Kostenec's avatar Michal Kostenec
Browse files

Authorization updated

Mapping id updated
Category 'test' supported
Filtering by parent category
parent dcedb1ad
No related branches found
No related tags found
No related merge requests found
...@@ -193,25 +193,25 @@ class X509Authenticator(NoAuthenticator): ...@@ -193,25 +193,25 @@ class X509Authenticator(NoAuthenticator):
def authorize(self, env, client, method, event, args): def authorize(self, env, client, method, event, args):
# Authorize for debug
if (method == 'getDebug'):
return client if client[0]['debug'] == 1 else None
cl = None cl = None
service = event['Node'][0]['Name'] service = event['Node'][0]['Name']
test = 'Test' in event['Category']
for i in range(len(client)): for clx in client:
if client[i]['service'] == service: if clx['service'] == service:
cl = client[i] cl = clx
break break
if cl is None: if cl is None:
return None return None
# logging.debug(cl) # Authorize for sending events
# logging.debug(method)
# logging.debug(service)
# return True if (method == 'getEvents' and cl['read'])
if ((method == 'sendEvents' and cl['write'] == 1) or if ((method == 'sendEvents' and cl['write'] == 1) or
(method == 'getDebug' and cl['debug'] == 1) or (method == 'sendEvents' and cl['test'] == 1 and test)):
(method == 'sendEvents' and cl['test'] == 1 and service == 'Test')):
return cl return cl
return None return None
...@@ -275,7 +275,7 @@ class MySQL(Object): ...@@ -275,7 +275,7 @@ class MySQL(Object):
def get_client_by_name(self, name): def get_client_by_name(self, name):
format_strings = ','.join(['%s'] * len(name)) format_strings = ','.join(['%s'] * len(name))
self.crs.execute("SELECT `id`, `hostname`, `service`, `identity`, `read`, `write`, `debug`, `test` FROM `clients2` WHERE `valid` = 1 AND `hostname` IN (%s)" % format_strings, tuple(name)) self.crs.execute("SELECT cl.`id`, cl.`hostname`, s.`service`, s.`service_id`, s.`identity`, cl.`read`, s.`write`, s.`test`, cl.`debug` FROM `clients3` cl LEFT JOIN `services` s ON cl.`id` = s.`client_id` WHERE cl.`valid` = 1 AND s.`valid` = 1 AND `hostname` IN (%s)" % format_strings, tuple(name))
row = self.crs.fetchall() row = self.crs.fetchall()
return row if row else None return row if row else None
...@@ -319,17 +319,22 @@ class MySQL(Object): ...@@ -319,17 +319,22 @@ class MySQL(Object):
sqlwhere = [] sqlwhere = []
sqltemp = {} sqltemp = {}
if cat is not None and nocat is not None: if cat is not None and nocat is not None:
raise Error("Unrealizable conditions. Choose cat or nocat option.", 500, method='getEvents', raise Error("Unrealizable conditions. Choose cat or nocat option.", 500, method='getEvents',
exc=sys.exc_info(), detail={'cat': cat, 'nocat' : nocat}) exc=sys.exc_info(), detail={'cat': cat, 'nocat' : nocat})
if cat is not None or nocat is not None: if cat is not None or nocat is not None:
if cat is not None: if cat is not None:
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id IN (%s)", json.loads(cat)) parent_cats = []
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id IN (%s)", json.loads(cat), parent_cats)
for pcats in parent_cats:
sqltemp['cat'] += " %s category_id DIV %s = 1 " % (("OR" if sqltemp['cat'] else ""), pcats)
if nocat is not None: if nocat is not None:
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id NOT IN (%s)", json.loads(nocat)) parent_cats = []
sqltemp['cat'] = generateDynamicQuery(self, "Category", "category_id NOT IN (%s)", json.loads(nocat), parent_cats)
for pcats in parent_cats:
sqltemp['cat'] += " %s category_id DIV %s = 1 " % (("OR" if sqltemp['cat'] else ""), pcats)
sqlwhere.append("e.id IN (SELECT event_id FROM event_category_mapping4 WHERE %s)" % sqltemp['cat']) sqlwhere.append("e.id IN (SELECT event_id FROM event_category_mapping4 WHERE %s)" % sqltemp['cat'])
if tag is not None and notag is not None: if tag is not None and notag is not None:
...@@ -369,12 +374,20 @@ class MySQL(Object): ...@@ -369,12 +374,20 @@ class MySQL(Object):
#sqlwhere = sqlwhere[:-4] #sqlwhere = sqlwhere[:-4]
and_op = "" if not sqlwhere_string else "AND" and_op = "" if not sqlwhere_string else "AND"
# logging.debug("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count))) logging.debug("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count)))
self.crs.execute("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count))) self.crs.execute("SELECT e.id, e.data FROM clients2 cl RIGHT JOIN events4 e ON cl.id = e.client_id WHERE e.id > %s AND %s %s e.valid = 1 LIMIT %s" % (str(id), sqlwhere_string, and_op, str(count)))
row = self.crs.fetchall() row = self.crs.fetchall()
if row:
maxid = max(r['id'] for r in row)
else:
maxid = self.getLastEventId()
# logging.debug("MAX ID = %s", str(maxid))
return { return {
"lastid": row[-1]['id'] if row else str(id), "lastid": maxid,
# "lastid": row[-1]['id'] if row else str(id),
"events": [row[i]['data'] for i in range(len(row))] "events": [row[i]['data'] for i in range(len(row))]
} }
...@@ -409,7 +422,31 @@ class MySQL(Object): ...@@ -409,7 +422,31 @@ class MySQL(Object):
return errs return errs
def map_id (self, section, key): def insertLastReceivedId(self, client, id):
logging.debug("INSERT INTO last_events(client_id, event_id, timestamp) VALUES(%s, %s, NOW())" % (str(client[0]['id']), id))
self.crs.execute("INSERT INTO last_events(client_id, event_id, timestamp) VALUES(%s, %s, NOW())" % (str(client[0]['id']), id))
def getLastEventId(self):
self.crs.execute("SELECT MAX(id) as id FROM events4")
row = self.crs.fetchone()
return row['id'] if row['id'] is not None else 0
def getLastReceivedId(self, client):
logging.debug("IN getLastReceivedId")
client_id = client[0]['id']
logging.debug("getLastReceivedId (client_id) = %s", str(client_id))
logging.debug("SELECT MAX(event_id) as id FROM last_events WHERE client_id = %s" % (str(client_id)))
self.crs.execute("SELECT MAX(event_id) as id FROM last_events WHERE client_id = %s" % (str(client_id)))
row = self.crs.fetchone()
logging.debug("getLastReceivedId - %s" % str(row['id']))
return row['id'] if row is not None else 0
def map_id (self, section, key, strict = False):
# Should by placed in config file # Should by placed in config file
data = {} data = {}
data['Tag'] = { data['Tag'] = {
...@@ -429,41 +466,51 @@ class MySQL(Object): ...@@ -429,41 +466,51 @@ class MySQL(Object):
"Other" : 99 "Other" : 99
} }
data['Category'] = { data['Category'] = {
"Abusive" : 100,
"Abusive.Spam" : 101, "Abusive.Spam" : 101,
"Abusive.Harassment" : 102, "Abusive.Harassment" : 102,
"Abusive.Child" : 103, "Abusive.Child" : 103,
"Abusive.Sexual" : 104, "Abusive.Sexual" : 104,
"Abusive.Violence" : 105, "Abusive.Violence" : 105,
"Malware" : 200,
"Malware.Virus" : 201, "Malware.Virus" : 201,
"Malware.Worm" : 202, "Malware.Worm" : 202,
"Malware.Trojan" : 203, "Malware.Trojan" : 203,
"Malware.Spyware" : 204, "Malware.Spyware" : 204,
"Malware.Dialer" : 205, "Malware.Dialer" : 205,
"Malware.Rootkit" : 206, "Malware.Rootkit" : 206,
"Recon.Scanning" : 3,
"Recon.Scanning" : 301, "Recon.Scanning" : 301,
"Recon.Sniffing" : 302, "Recon.Sniffing" : 302,
"Recon.SocialEngineering" : 303, "Recon.SocialEngineering" : 303,
"Recon.Searching" : 304, "Recon.Searching" : 304,
"Attempt" : 400,
"Attempt.Exploit" : 401, "Attempt.Exploit" : 401,
"Attempt.Login" : 402, "Attempt.Login" : 402,
"Attempt.NewSignature" : 403, "Attempt.NewSignature" : 403,
"Intrusion" : 500,
"Intrusion.AdminCompromise" : 501, "Intrusion.AdminCompromise" : 501,
"Intrusion.UserCompromise" : 502, "Intrusion.UserCompromise" : 502,
"Intrusion.AppCompromise" : 503, "Intrusion.AppCompromise" : 503,
"Intrusion.Botnet" : 504, "Intrusion.Botnet" : 504,
"Availability" : 600,
"Availability.DoS" : 601, "Availability.DoS" : 601,
"Availability.DDoS" : 602, "Availability.DDoS" : 602,
"Availability.Sabotage" : 603, "Availability.Sabotage" : 603,
"Availability.Outage" : 604, "Availability.Outage" : 604,
"Information" : 700,
"Information.UnauthorizedAccess" : 701, "Information.UnauthorizedAccess" : 701,
"Information.UnauthorizedModification" : 702, "Information.UnauthorizedModification" : 702,
"Fraud" : 800,
"Fraud.UnauthorizedUsage" : 801, "Fraud.UnauthorizedUsage" : 801,
"Fraud.Copyright" : 802, "Fraud.Copyright" : 802,
"Fraud.Masquerade" : 803, "Fraud.Masquerade" : 803,
"Fraud.Phishing" : 804, "Fraud.Phishing" : 804,
"Fraud.Scam" : 805, "Fraud.Scam" : 805,
"Vulnerable" : 900,
"Vulnerable.Open" : 901, "Vulnerable.Open" : 901,
"Anomaly" : 1000,
"Anomaly.Traffic" : 1001, "Anomaly.Traffic" : 1001,
"Anomaly.Connection" : 1002, "Anomaly.Connection" : 1002,
"Anomaly.Protocol" : 1003, "Anomaly.Protocol" : 1003,
...@@ -477,16 +524,27 @@ class MySQL(Object): ...@@ -477,16 +524,27 @@ class MySQL(Object):
try: try:
return data[section][key] return data[section][key]
except: except:
return data[section]['Other'] #Return 0 for strict mode (searching), otherwise map everything else to 'Other'
return 0 if strict else data[section]['Other']
def generateDynamicQuery(self, section, query_string, variables, parent_cats = []):
variables_id = []
# parent_cats = []
def generateDynamicQuery(self, section, query_string, variables): for v in variables:
variables_id = [self.map_id(section, v) for v in variables] mapped_id = self.map_id(section, v, True)
if mapped_id % 100 != 0:
variables_id.append(mapped_id)
else:
parent_cats.append(mapped_id)
# variables_id = [self.map_id(section, v) for v in variables if self.map_id(section, v) % 100 != 0]
format_strings = ','.join(['\'%s\''] * len(variables_id)) format_strings = ','.join(['\'%s\''] * len(variables_id))
temp_string = query_string % format_strings temp_string = query_string % format_strings
return temp_string % tuple(variables_id) return temp_string % tuple(variables_id)
def expose(meth): def expose(meth):
meth.exposed = True meth.exposed = True
return meth return meth
...@@ -627,6 +685,10 @@ class WardenHandler(Object): ...@@ -627,6 +685,10 @@ class WardenHandler(Object):
@expose @expose
def getDebug(self, _env, _client): def getDebug(self, _env, _client):
auth = self.auth.authorize(_env, _client, 'getDebug', None, None)
if not auth:
raise Error("I'm watching YOU. (Authorization)", 403, method='getDebug', detail={"client": _client})
return { return {
"environment": _env, "environment": _env,
"database": self.db.get_debug() "database": self.db.get_debug()
...@@ -656,6 +718,27 @@ class WardenHandler(Object): ...@@ -656,6 +718,27 @@ class WardenHandler(Object):
except (ValueError, TypeError): except (ValueError, TypeError):
id=0 id=0
if id == 0:
try:
id = self.db.getLastReceivedId(_client)
# logging.debug("Last received ID for %s is %s" % (_client['hostname'], str(id)))
except Exception, e:
logging.error(e)
id = 0
if id == 0:
try:
id = self.db.getLastEventId()
except Exception as e:
raise Error("Last event id receiving error", 500, detail={"client": _client})
self.db.insertLastReceivedId(_client, id)
return {
"lastid": id,
"events": []
}
try: try:
count = int(count) count = int(count)
except (ValueError, TypeError): except (ValueError, TypeError):
...@@ -669,6 +752,9 @@ class WardenHandler(Object): ...@@ -669,6 +752,9 @@ class WardenHandler(Object):
logging.info("getEvents(%d, %d, %s, %s, %s, %s, %s, %s): sending %d events" % ( logging.info("getEvents(%d, %d, %s, %s, %s, %s, %s, %s): sending %d events" % (
id, count, cat, nocat, tag, notag, group, nogroup, len(res["events"]))) id, count, cat, nocat, tag, notag, group, nogroup, len(res["events"])))
self.db.insertLastReceivedId(_client, res['lastid'])
logging.debug("lastid inserting: %s" % {'lastid': res['lastid'], 'client' : _client})
return res return res
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment