* build dependent http-proxy as ARG

* extended exception handling now meets the requirements of REST
* README cosmetics
This commit is contained in:
Dominik Chilla 2018-12-31 00:51:11 +01:00
parent 259aec5a96
commit ebe8742776
9 changed files with 271 additions and 55 deletions

View File

@ -1,2 +1,48 @@
# gulag # gulag
Gulag quarantine Gulag quarantine
## curl examples
### get all QuarMail metadata
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails | jq
```
### get all QuarMail metadata + RFC822 messages
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails?rfc822_message=1 | jq
```
### get QuarMails metadata by (jqgrid-style) filter
```curl -v -s -G --data-urlencode 'filters={"groupOp":"OR","rules":[{"field":"hdr_subject","op":"eq","data":"996 test from quar mit sync xyz"}]}' http://127.0.0.1:9090/api/v1/quarmails | jq
```
### delete a QuarMail by ID
```curl -v -s -X DELETE http://127.0.0.1:9090/api/v1/quarmails/141 | jq
```
### get a QuarMail´s metadata by ID
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136 | jq
```
### get a QuarMail´s metadata by ID + RFC822 message
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136?rfc822_message=1 | jq
```
### get all URIs of a QuarMail
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136/uris | jq
```
### get an URI of a QuarMail by ID
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136/uris/249 | jq
```
### get all attachments metadata of a QuarMail
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136/attachments | jq
```
### get an attachments metadata of a QuarMail by ID
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136/attachments/71 | jq
```
### get an attachments metadata of a QuarMail by ID + attachment data
```curl -v -s http://127.0.0.1:9090/api/v1/quarmails/136/attachments/71?data=1 | jq
```

View File

@ -1,6 +1,8 @@
import json, sys,os,logging,re,magic import json, sys,os,logging,re,magic
import email,email.header,email.message import email,email.header,email.message
from GulagDB import GulagDB,GulagDBException from GulagDB import (
GulagDB,GulagDBException,GulagDBNotFoundException,GulagDBBadInputException
)
from GulagMailbox import IMAPmailbox,IMAPmailboxException from GulagMailbox import IMAPmailbox,IMAPmailboxException
from GulagUtils import whoami,extract_uris,extract_fqdn from GulagUtils import whoami,extract_uris,extract_fqdn
import ssdeep, hashlib import ssdeep, hashlib
@ -10,6 +12,16 @@ class GulagException(Exception):
def __init__(self,message): def __init__(self,message):
self.message = message self.message = message
class GulagNotFoundException(Exception):
message = None
def __init__(self,message):
self.message = message
class GulagBadInputException(Exception):
message = None
def __init__(self,message):
self.message = message
class Gulag: class Gulag:
version = None version = None
config = None config = None
@ -231,6 +243,8 @@ class Gulag:
try: try:
self.check_fields('QuarMails',args) self.check_fields('QuarMails',args)
qms_db = self.db.get_quarmails(args) qms_db = self.db.get_quarmails(args)
except GulagDBBadInputException as e:
raise GulagBadInputException(whoami(self) + e.message) from e
except(GulagException,GulagDBException) as e: except(GulagException,GulagDBException) as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -278,6 +292,8 @@ class Gulag:
qm_db = None qm_db = None
try: try:
qm_db = self.db.get_quarmail({"id": args['quarmail_id']}) qm_db = self.db.get_quarmail({"id": args['quarmail_id']})
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -287,6 +303,8 @@ class Gulag:
mailbox = None mailbox = None
try: try:
mailbox = self.db.get_mailbox(qm_db['mailbox_id']) mailbox = self.db.get_mailbox(qm_db['mailbox_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -306,12 +324,16 @@ class Gulag:
qm_db = None qm_db = None
try: try:
qm_db = self.db.get_quarmail({"id": args['quarmail_id']}) qm_db = self.db.get_quarmail({"id": args['quarmail_id']})
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
mailbox = None mailbox = None
try: try:
mailbox = self.db.get_mailbox(qm_db['mailbox_id']) mailbox = self.db.get_mailbox(qm_db['mailbox_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -341,7 +363,7 @@ class Gulag:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
imap_mb.close() imap_mb.close()
return True return
def get_quarmail_attachments(self,args): def get_quarmail_attachments(self,args):
try: try:
@ -356,6 +378,8 @@ class Gulag:
qmat_db = self.db.get_quarmail_attachment( qmat_db = self.db.get_quarmail_attachment(
args['quarmail_id'],args['attachment_id'] args['quarmail_id'],args['attachment_id']
) )
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -365,6 +389,8 @@ class Gulag:
mailbox = None mailbox = None
try: try:
mailbox = self.db.get_mailbox(qmat_db['mailbox_id']) mailbox = self.db.get_mailbox(qmat_db['mailbox_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -384,6 +410,8 @@ class Gulag:
at_db = None at_db = None
try: try:
at_db = self.db.get_attachment({"id": args['id']}) at_db = self.db.get_attachment({"id": args['id']})
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
if 'data' not in args: if 'data' not in args:
@ -399,12 +427,16 @@ class Gulag:
qm_db = None qm_db = None
try: try:
qm_db = self.db.get_quarmail({"id": args['quarmail_id']}) qm_db = self.db.get_quarmail({"id": args['quarmail_id']})
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
mailbox = None mailbox = None
try: try:
mailbox = self.db.get_mailbox(qm_db['mailbox_id']) mailbox = self.db.get_mailbox(qm_db['mailbox_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
@ -424,10 +456,20 @@ class Gulag:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
def get_quarmail_uri(self,args):
try:
return self.db.get_quarmail_uri(args['quarmail_id'],args['uri_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e:
raise GulagException(whoami(self) + e.message) from e
def rspamd_http2imap(self,args): def rspamd_http2imap(self,args):
mailbox = None mailbox = None
try: try:
mailbox = self.db.get_mailbox(args['mailbox_id']) mailbox = self.db.get_mailbox(args['mailbox_id'])
except GulagDBNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
# check if the request comes really from rspamd´s metadata_exporter # check if the request comes really from rspamd´s metadata_exporter

View File

@ -11,6 +11,16 @@ class GulagDBException(Exception):
def __init__(self,message): def __init__(self,message):
self.message = str(message) self.message = str(message)
class GulagDBNotFoundException(Exception):
message = None
def __init__(self,message):
self.message = str(message)
class GulagDBBadInputException(Exception):
message = None
def __init__(self,message):
self.message = str(message)
class GulagDB: class GulagDB:
conn = None conn = None
uri_prefixes = None uri_prefixes = None
@ -51,8 +61,8 @@ class GulagDB:
cursor.execute(query) cursor.execute(query)
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) raise GulagDBNotFoundException(whoami(self)
+ "describe " + table_name + " failed!" + "describe " + table_name + " failed: got no fields!"
) )
desc = cursor.description desc = cursor.description
cursor.close() cursor.close()
@ -70,21 +80,25 @@ class GulagDB:
try: try:
int(args['query_offset']) int(args['query_offset'])
except ValueError: except ValueError:
raise GulagDBException(whoami(self) + "query_offset must be numeric!") raise GulagDBBadInputException(whoami(self) +
"query_offset must be numeric!"
)
try: try:
int(args['query_limit']) int(args['query_limit'])
except ValueError: except ValueError:
raise GulagDBException(whoami(self) + "query_limit must be numeric!") raise GulagDBBadInputException(whoami(self) +
"query_limit must be numeric!"
)
return "limit "+args['query_offset']+","+args['query_limit'] return "limit "+args['query_offset']+","+args['query_limit']
elif('query_offset' in args and 'query_limit' not in args): elif('query_offset' in args and 'query_limit' not in args):
raise GulagDBException(whoami(self) + raise GulagDBBadInputException(whoami(self) +
"query_offset without query_limit is useless!" "query_offset without query_limit is useless!"
) )
elif('query_limit' in args and 'query_offset' not in args): elif('query_limit' in args and 'query_offset' not in args):
try: try:
int(args['query_limit']) int(args['query_limit'])
except ValueError: except ValueError:
raise GulagDBException(whoami(self) + "query_limit must be numeric!") raise GulagDBBadInputException(whoami(self) + "query_limit must be numeric!")
return "limit " + args['query_limit'] return "limit " + args['query_limit']
else: else:
return "" return ""
@ -110,21 +124,31 @@ class GulagDB:
def get_where_clause_from_filters(self,filters): def get_where_clause_from_filters(self,filters):
# {"groupOp":"AND","rules":[{"field":"uri_count","op":"eq","data":"3"}]} # {"groupOp":"AND","rules":[{"field":"uri_count","op":"eq","data":"3"}]}
if 'rules' not in filters: if 'rules' not in filters:
raise GulagDBException(whoami(self) + "no 'rules' found in filters!") raise GulagDBBadInputException(whoami(self) +
"no 'rules' found in filters!"
)
if 'groupOp' not in filters: if 'groupOp' not in filters:
raise GulagDBException(whoami(self) + "'groupOp' not found in filters!") raise GulagDBBadInputException(whoami(self) +
"'groupOp' not found in filters!"
)
if filters['groupOp'] != 'AND' and filters['groupOp'] != 'OR': if filters['groupOp'] != 'AND' and filters['groupOp'] != 'OR':
raise GulagDBException(whoami(self) + raise GulagDBBadInputException(whoami(self) +
"invalid 'groupOp': " + filters['groupOp'] "invalid 'groupOp': " + filters['groupOp']
) )
where_clause = "" where_clause = ""
for rule in filters['rules']: for rule in filters['rules']:
if 'field' not in rule: if 'field' not in rule:
raise GulagDBException(whoami(self) + "'field' not found in rule!") raise GulagDBBadInputException(whoami(self) +
"'field' not found in rule!"
)
if 'op' not in rule: if 'op' not in rule:
raise GulagDBException(whoami(self) + "'op' not found in rule!") raise GulagDBBadInputException(whoami(self) +
"'op' not found in rule!"
)
if 'data' not in rule: if 'data' not in rule:
raise GulagDBException(whoami(self) + "'data' not found in rule!") raise GulagDBBadInputException(whoami(self) +
"'data' not found in rule!"
)
field_op_data = None field_op_data = None
if(rule['op'] == 'eq'): if(rule['op'] == 'eq'):
field_op_data = rule['field'] + "='" + rule['data'] + "'" field_op_data = rule['field'] + "='" + rule['data'] + "'"
@ -141,7 +165,9 @@ class GulagDB:
elif(rule['op'] == 'lt'): elif(rule['op'] == 'lt'):
field_op_data = rule['field'] + " < '" + rule['data'] + "'" field_op_data = rule['field'] + " < '" + rule['data'] + "'"
if(field_op_data == None): if(field_op_data == None):
raise GulagDBException(whoami(self) + "invalid rule-op: " + rule['op']) raise GulagDBBadInputException(whoami(self) +
"invalid rule-op: " + rule['op']
)
if(len(filters['rules']) == 1 or len(where_clause) == 0): if(len(filters['rules']) == 1 or len(where_clause) == 0):
if rule['field'] in self.vcols: if rule['field'] in self.vcols:
where_clause = "having " + field_op_data where_clause = "having " + field_op_data
@ -158,7 +184,7 @@ class GulagDB:
results = [] results = []
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) + "No mailboxes found in DB!") return results
desc = cursor.description desc = cursor.description
for tuple in data: for tuple in data:
dict = {} dict = {}
@ -182,7 +208,7 @@ class GulagDB:
) )
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) raise GulagDBNotFoundException(whoami(self)
+ "Mailbox '" + mailbox_id + "' does not exist!" + "Mailbox '" + mailbox_id + "' does not exist!"
) )
desc = cursor.description desc = cursor.description
@ -259,6 +285,8 @@ class GulagDB:
dict['href'] = self.uri_prefixes['quarmails'] + str(dict['id']) dict['href'] = self.uri_prefixes['quarmails'] + str(dict['id'])
results.append(QuarMail(dict).__dict__) results.append(QuarMail(dict).__dict__)
return results return results
except GulagDBBadInputException as e:
raise GulagDBBadInputException(whoami(self) + e.message) from e
except GulagDBException as e: except GulagDBException as e:
raise GulagDBException(whoami(self) + e.message) from e raise GulagDBException(whoami(self) + e.message) from e
except mariadb.Error as e: except mariadb.Error as e:
@ -275,7 +303,7 @@ class GulagDB:
cursor.execute(query) cursor.execute(query)
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) raise GulagDBNotFoundException(whoami(self)
+ "Quarmail with id '"+ str(args['id']) + "' does not exist!" + "Quarmail with id '"+ str(args['id']) + "' does not exist!"
) )
desc = cursor.description desc = cursor.description
@ -288,10 +316,6 @@ class GulagDB:
else: else:
dict[name[0]] = value dict[name[0]] = value
dict['href'] = self.uri_prefixes['quarmails'] + str(dict['id']) dict['href'] = self.uri_prefixes['quarmails'] + str(dict['id'])
# try:
# dict['attachments'] = self.get_attachments_by_quarmail(args['id'])
# except GulagDBException as e:
# pass
return QuarMail(dict).__dict__ return QuarMail(dict).__dict__
except mariadb.Error as e: except mariadb.Error as e:
raise GulagDBException(whoami(self) + str(e)) from e raise GulagDBException(whoami(self) + str(e)) from e
@ -363,7 +387,7 @@ class GulagDB:
cursor.execute(query) cursor.execute(query)
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) raise GulagDBNotFoundException(whoami(self)
+ "Attachment("+ str(args['id']) +") does not exist!" + "Attachment("+ str(args['id']) +") does not exist!"
) )
desc = cursor.description desc = cursor.description
@ -413,8 +437,9 @@ class GulagDB:
cursor.execute(query) cursor.execute(query)
data = cursor.fetchall() data = cursor.fetchall()
if not data: if not data:
raise GulagDBException(whoami(self) + "QuarMail("+ str(quarmail_id) +") " raise GulagDBNotFoundException(whoami(self) +
+ "has no attachment (" + str(attachment_id) + ")!" "QuarMail("+ str(quarmail_id) +") " +
"has no attachment (" + str(attachment_id) + ")!"
) )
desc = cursor.description desc = cursor.description
tuple = data[0] tuple = data[0]
@ -497,6 +522,36 @@ class GulagDB:
except mariadb.Error as e: except mariadb.Error as e:
raise GulagDBException(whoami(self) + str(e)) from e raise GulagDBException(whoami(self) + str(e)) from e
def get_quarmail_uri(self,quarmail_id,uri_id):
try:
query = "select URIs.*"
query += " from QuarMail2URI"
query += " left join QuarMails ON QuarMails.id = QuarMail2URI.quarmail_id"
query += " left join URIs ON URIs.id = QuarMail2URI.uri_id"
query += " where QuarMails.id = " + str(quarmail_id)
query += " and URIs.id = " + str(uri_id) + ";"
cursor = self.conn.cursor()
cursor.execute(query)
data = cursor.fetchall()
if not data:
raise GulagDBNotFoundException(whoami(self) +
"QuarMail("+ str(quarmail_id) +")" +
" has no uri (" + str(uri_id) + ")!"
)
desc = cursor.description
tuple = data[0]
dict = {}
for (name, value) in zip(desc, tuple):
dict[name[0]] = value
dict['href'] = self.uri_prefixes['quarmails'] + str(quarmail_id)
dict['href'] += "/uris/" + str(dict['id'])
try:
return URI(dict).__dict__
except URIException as e:
raise GulagDBException(whoami(self) + e.message) from e
except mariadb.Error as e:
raise GulagDBException(whoami(self) + str(e)) from e
def delete_quarmail_uris(self, quarmail_id): def delete_quarmail_uris(self, quarmail_id):
cursor = None cursor = None
try: try:

View File

@ -1,7 +1,9 @@
from flask import request from flask import request, Response
from flask_restful import Resource, abort, reqparse from flask_restful import Resource, abort, reqparse
from Gulag import GulagException
import json import json
from Gulag import (
GulagException,GulagNotFoundException,GulagBadInputException
)
class GulagResource(Resource): class GulagResource(Resource):
gulag = None gulag = None
@ -37,7 +39,7 @@ class ResMailboxes(GulagResource):
try: try:
return self.gulag.get_mailboxes() return self.gulag.get_mailboxes()
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResMailbox(GulagResource): class ResMailbox(GulagResource):
def get(self,id): def get(self,id):
@ -50,11 +52,13 @@ class ResQuarMails(GulagResource):
try: try:
args['filters'] = json.loads(args['filters']) args['filters'] = json.loads(args['filters'])
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
abort(400, message=whoami(self) + "JSON parse error: " + e.msg) abort(400, message="Invalid filters: " + e.msg)
try: try:
return self.gulag.get_quarmails(args) return self.gulag.get_quarmails(args)
except GulagException as e: except GulagBadInputException as e:
abort(400, message=e.message) abort(400, message=e.message)
except GulagException as e:
abort(500, message=e.message)
class ResQuarMail(GulagResource): class ResQuarMail(GulagResource):
def get(self,quarmail_id): def get(self,quarmail_id):
@ -63,14 +67,19 @@ class ResQuarMail(GulagResource):
if(request.args.get('rfc822_message')): if(request.args.get('rfc822_message')):
args['rfc822_message'] = True args['rfc822_message'] = True
return self.gulag.get_quarmail(args) return self.gulag.get_quarmail(args)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
def delete(self,quarmail_id): def delete(self,quarmail_id):
args = {"quarmail_id": quarmail_id} args = {"quarmail_id": quarmail_id}
try: try:
return self.gulag.delete_quarmail(args) self.gulag.delete_quarmail(args)
return Response(response=None,status=202,mimetype=None)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResQuarMailAttachments(GulagResource): class ResQuarMailAttachments(GulagResource):
def get(self,quarmail_id): def get(self,quarmail_id):
@ -80,7 +89,7 @@ class ResQuarMailAttachments(GulagResource):
try: try:
return self.gulag.get_quarmail_attachments(args) return self.gulag.get_quarmail_attachments(args)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResQuarMailAttachment(GulagResource): class ResQuarMailAttachment(GulagResource):
def get(self,quarmail_id,attachment_id): def get(self,quarmail_id,attachment_id):
@ -92,8 +101,10 @@ class ResQuarMailAttachment(GulagResource):
args['data'] = True args['data'] = True
try: try:
return self.gulag.get_quarmail_attachment(args) return self.gulag.get_quarmail_attachment(args)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResQuarMailURIs(GulagResource): class ResQuarMailURIs(GulagResource):
def get(self,quarmail_id): def get(self,quarmail_id):
@ -105,7 +116,20 @@ class ResQuarMailURIs(GulagResource):
try: try:
return self.gulag.get_quarmail_uris(args) return self.gulag.get_quarmail_uris(args)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResQuarMailURI(GulagResource):
def get(self,quarmail_id,uri_id):
args = {
"quarmail_id": quarmail_id,
"uri_id": uri_id
}
try:
return self.gulag.get_quarmail_uri(args)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e:
abort(500, message=e.message)
class ResAttachments(GulagResource): class ResAttachments(GulagResource):
def get(self): def get(self):
@ -116,8 +140,10 @@ class ResAttachment(GulagResource):
args = {"id": attachment_id} args = {"id": attachment_id}
try: try:
return self.gulag.get_attachment(args) return self.gulag.get_attachment(args)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)
class ResRSPAMDImporter(GulagResource): class ResRSPAMDImporter(GulagResource):
def post(self,mailbox_id): def post(self,mailbox_id):
@ -127,8 +153,15 @@ class ResRSPAMDImporter(GulagResource):
"req_headers": request.headers, "req_headers": request.headers,
"rfc822_message": request.get_data(as_text=True) "rfc822_message": request.get_data(as_text=True)
}) })
# TODO: Response mit Location-Header? return {}
# https://stackoverflow.com/a/22707491 # response = Response(
return {"resource: ": "HTTP2IMAP for RSPAMD"} # response=json.dumps(resp),
# status=201,
# mimetype='application/json',
# headers=Headers([
# ('Location', 'https://invalid.local/api/v1/blablabla/123')
# ])
# )
# return response
except GulagException as e: except GulagException as e:
abort(400, message=e.message) abort(500, message=e.message)

View File

@ -7,7 +7,7 @@ from Gulag import Gulag,GulagException
from Resources import (ResRoot,ResMailboxes, from Resources import (ResRoot,ResMailboxes,
ResQuarMails,ResQuarMail,ResQuarMailAttachments, ResQuarMails,ResQuarMail,ResQuarMailAttachments,
ResQuarMailAttachment,ResAttachments,ResAttachment, ResQuarMailAttachment,ResAttachments,ResAttachment,
ResRSPAMDImporter,ResQuarMailURIs ResRSPAMDImporter,ResQuarMailURIs,ResQuarMailURI
) )
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--config', required=True, help="Path to config file") parser.add_argument('--config', required=True, help="Path to config file")
@ -19,6 +19,8 @@ try:
except GulagException as e: except GulagException as e:
raise Exception(e.message) from e raise Exception(e.message) from e
app = Flask(__name__) app = Flask(__name__)
# https://github.com/flask-restful/flask-restful/issues/780#issuecomment-434588559
app.config['ERROR_404_HELP'] = False
api = Api(app, catch_all_404s=True) api = Api(app, catch_all_404s=True)
api.add_resource(ResRoot, api.add_resource(ResRoot,
'/api/v1/', '/api/v1/',
@ -48,6 +50,10 @@ try:
'/api/v1/quarmails/<int:quarmail_id>/uris', '/api/v1/quarmails/<int:quarmail_id>/uris',
resource_class_kwargs={'gulag_object': gulag} resource_class_kwargs={'gulag_object': gulag}
) )
api.add_resource(ResQuarMailURI,
'/api/v1/quarmails/<int:quarmail_id>/uris/<int:uri_id>',
resource_class_kwargs={'gulag_object': gulag}
)
api.add_resource(ResAttachments, api.add_resource(ResAttachments,
'/api/v1/attachments', '/api/v1/attachments',
resource_class_kwargs={'gulag_object': gulag} resource_class_kwargs={'gulag_object': gulag}

View File

@ -22,7 +22,11 @@ fi
IMAGES="gulag-server gulag-db" IMAGES="gulag-server gulag-db"
for IMAGE in ${IMAGES}; do for IMAGE in ${IMAGES}; do
/usr/bin/docker build -t "${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" -f "docker/${IMAGE}/${BASEOS}/Dockerfile" . /usr/bin/docker build \
--build-arg http_proxy=http://wprx-zdf.zwackl.local:3128 \
--build-arg https_proxy=http://wprx-zdf.zwackl.local:3128 \
-t "${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" \
-f "docker/${IMAGE}/${BASEOS}/Dockerfile" .
# /usr/bin/docker tag "${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" "${REGISTRY}/${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" # /usr/bin/docker tag "${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" "${REGISTRY}/${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}"
done done
@ -30,4 +34,3 @@ done
#for IMAGE in ${IMAGES}; do #for IMAGE in ${IMAGES}; do
# /bin/echo "/usr/bin/docker push ${REGISTRY}/${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}" # /bin/echo "/usr/bin/docker push ${REGISTRY}/${IMAGE}/${BASEOS}:${VERSION}_${BRANCH}"
#done #done

View File

@ -1,3 +1,5 @@
ARG http_proxy
ARG https_proxy
FROM debian FROM debian
RUN apt update && \ RUN apt update && \
apt -yq --no-install-recommends install procps net-tools mariadb-server mariadb-client apt -yq --no-install-recommends install procps net-tools mariadb-server mariadb-client

View File

@ -1,17 +1,19 @@
ARG http_proxy
ARG https_proxy
FROM debian FROM debian
LABEL maintainer="Dominik Chilla" LABEL maintainer="Dominik Chilla"
ENV DEBIAN_FRONTEND=noninteractive \ ENV DEBIAN_FRONTEND=noninteractive \
TZ=Europe/Berlin TZ=Europe/Berlin
RUN set -ex ; \ RUN env; set -ex ; \
apt-get -qq update \ apt-get -qq update \
&& apt-get -qq --no-install-recommends install \ && apt-get -qq --no-install-recommends install \
uwsgi-plugin-python3 python3-setuptools python3-flask \ uwsgi-plugin-python3 python3-setuptools python3-flask \
python3-flask-restful python3-mysql.connector \ python3-flask-restful python3-mysql.connector \
uwsgi uwsgi-plugin-python3 procps net-tools \ uwsgi uwsgi-plugin-python3 procps net-tools \
python3-pip libmagic1 python3-ssdeep \ python3-pip libmagic1 python3-ssdeep \
&& pip3 install python-magic && pip3 install python-magic \
&& /bin/mkdir /config /socket /app
RUN /bin/mkdir /config /socket /app
COPY app/*.py /app/ COPY app/*.py /app/

View File

@ -1,6 +1,6 @@
swagger: '2.0' swagger: '2.0'
info: info:
description: Gulag quarantine REST API description: https://app.swaggerhub.com/apis/DC-IT-Consulting/Gulag/1.0.0#/
version: "1.0.0" version: "1.0.0"
title: Gulag quarantine REST API title: Gulag quarantine REST API
contact: contact:
@ -173,10 +173,10 @@ paths:
required: true required: true
type: integer type: integer
responses: responses:
200: 202:
description: quarantined email deleted description: quarantined email deleted
400: 404:
description: bad input parameter description: not found
500: 500:
description: server error description: server error
@ -228,11 +228,11 @@ paths:
required: false required: false
responses: responses:
200: 200:
description: quarantined email object description: attachment object
schema: schema:
$ref: '#/definitions/Attachment' $ref: '#/definitions/Attachment'
400: 404:
description: bad input parameter description: not found
500: 500:
description: server error description: server error
@ -265,6 +265,33 @@ paths:
500: 500:
description: server error description: server error
/quarmails/{quarmail_id}/uris/{uri_id}:
get:
summary: "returns an URI by ID"
operationId: get_quarmail_uri
produces:
- application/json
parameters:
- in: path
name: quarmail_id
description: unique id of quarantined email
required: true
type: string
- in: path
name: uri_id
description: id of URI to fetch
required: true
type: string
responses:
200:
description: URI object
schema:
$ref: '#/definitions/URI'
404:
description: not found
500:
description: server error
definitions: definitions:
QuarMail: QuarMail:
type: object type: object