forked from mlsecproject/gglsbl-rest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
82 lines (69 loc) · 2.5 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import logging.config
import time
from os import environ, path
from flask import Flask, request, jsonify, abort
from gglsbl import SafeBrowsingList
from multiprocessing import cpu_count
# basic app configuration and options
app = Flask("gglsbl-rest")
gsb_api_key = environ['GSB_API_KEY']
dbfile = path.join(environ.get('GSB_DB_DIR', '/tmp'), 'sqlite.db')
environment = environ.get('ENVIRONMENT', 'prod').lower()
max_retries = int(environ.get('MAX_RETRIES', "3"))
# Keep last query object so we can try to re-use it across requests
sbl = None
last_api_key = None
def _lookup(url, api_key, retry=1):
# perform lookup
global sbl, last_api_key
try:
if api_key != last_api_key:
app.logger.info('re-opening database')
sbl = SafeBrowsingList(api_key, dbfile, True)
last_api_key = api_key
return sbl.lookup_url(url)
except:
app.logger.exception("exception handling [" + url + "]")
if retry >= max_retries:
sbl = None
last_api_key = None
abort(500)
else:
return _lookup(url, api_key, retry + 1)
@app.route('/gglsbl/lookup/<path:url>', methods=['GET'])
@app.route('/gglsbl/v1/lookup/<path:url>', methods=['GET'])
def app_lookup(url):
# input validation
if not isinstance(url, (str, unicode)):
abort(400)
# find out which API key to use
api_key = request.headers.get('x-gsb-api-key', gsb_api_key)
if not api_key:
app.logger.error('no API key to use')
abort(401)
# look up URL
resp = _lookup(url, api_key)
if resp:
matches = [{'threat': x.threat_type, 'platform': x.platform_type,
'threat_entry': x.threat_entry_type} for x in resp]
return jsonify({'url': url, 'matches': matches})
else:
abort(404)
@app.route('/gglsbl/status', methods=['GET'])
@app.route('/gglsbl/v1/status', methods=['GET'])
def status_page():
retval = {
'environment': environment,
'alternatives': [{
'active': True,
'name': dbfile,
'mtime': time.strftime('%Y-%m-%dT%H:%M:%S%z', time.gmtime(path.getmtime(dbfile))),
'ctime': time.strftime('%Y-%m-%dT%H:%M:%S%z', time.gmtime(path.getctime(dbfile))),
'size': path.getsize(dbfile)
}]
}
return jsonify(retval)
# run internal Flask server if executed directly
if __name__ == '__main__':
logging.config.fileConfig('logging.conf')
app.run(processes=int(environ.get('WORKERS', cpu_count() * 2 + 1)))