mirror of
https://github.com/opnsense/plugins.git
synced 2026-05-28 04:34:15 -04:00
security/q-feeds-connector: add optional locked mode in qfeedsctl.py for cron runners and wait for configfile changes when HTTP 401 is thrown. closes https://github.com/opnsense/plugins/issues/5416
This should prevent firewalls from spamming Q-Feeds infrastructure when either an empty or invalid token is specified.
This commit is contained in:
parent
11ac729b07
commit
7b3b5a4e3c
3 changed files with 38 additions and 4 deletions
|
|
@ -29,16 +29,24 @@ from configparser import ConfigParser
|
|||
|
||||
|
||||
class QFeedsConfig:
|
||||
config_filename = '/usr/local/etc/qfeeds.conf'
|
||||
api_key = None
|
||||
conf_timestamp = None
|
||||
|
||||
def __init__(self):
|
||||
config_filename = '/usr/local/etc/qfeeds.conf'
|
||||
if os.path.isfile(config_filename):
|
||||
if os.path.isfile(self.config_filename):
|
||||
cnf = ConfigParser()
|
||||
cnf.read(config_filename)
|
||||
cnf.read(self.config_filename)
|
||||
if cnf.has_section('api') and cnf.has_option('api', 'key'):
|
||||
self.api_key = cnf.get('api', 'key').strip()
|
||||
|
||||
if self.conf_timestamp is None:
|
||||
QFeedsConfig.conf_timestamp = os.stat(self.config_filename).st_mtime
|
||||
|
||||
@classmethod
|
||||
def has_changed(cls):
|
||||
return os.path.isfile(cls.config_filename) and cls.conf_timestamp != os.stat(cls.config_filename).st_mtime
|
||||
|
||||
|
||||
class Api:
|
||||
def __init__(self):
|
||||
|
|
|
|||
|
|
@ -27,10 +27,13 @@
|
|||
"""
|
||||
|
||||
import argparse
|
||||
import fcntl
|
||||
import time
|
||||
import sys
|
||||
import ujson
|
||||
from requests.exceptions import HTTPError, Timeout
|
||||
from lib import QFeedsActions
|
||||
from lib.api import QFeedsConfig
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
@ -38,8 +41,20 @@ if __name__ == '__main__':
|
|||
parser.add_argument('--target_dir', default='/var/db/qfeeds-tables')
|
||||
parser.add_argument('-f', help='forced (auto index)' , default=False, action='store_true')
|
||||
parser.add_argument('-v', help='verbose output' , default=False, action='store_true')
|
||||
parser.add_argument('-l', help='lock operation' , default=False, action='store_true')
|
||||
parser.add_argument("action", choices=QFeedsActions.list_actions(), nargs='*')
|
||||
args = parser.parse_args()
|
||||
|
||||
fhandle = None
|
||||
if args.l:
|
||||
lck_filename = '/tmp/qfeeds_prc.LCK'
|
||||
fhandle = open(lck_filename, 'a+')
|
||||
try:
|
||||
fcntl.flock(fhandle, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except IOError:
|
||||
print('already busy, exit')
|
||||
sys.exit(0)
|
||||
|
||||
if args.v:
|
||||
# verbose mode
|
||||
import http.client as http_client
|
||||
|
|
@ -51,6 +66,14 @@ if __name__ == '__main__':
|
|||
print(msg)
|
||||
except HTTPError as exc:
|
||||
print('exit with HTTPError %d (%s)' % (exc.response.status_code, exc.response.text))
|
||||
if exc.response.status_code == 401 and 'update' in args.action:
|
||||
print('batch mode - wait for configuration update or timeout')
|
||||
t_start = time.time()
|
||||
while not QFeedsConfig.has_changed():
|
||||
if time.time() - t_start > 3600:
|
||||
print('timeout waiting for config change')
|
||||
break
|
||||
time.sleep(5)
|
||||
sys.exit(-1)
|
||||
except Timeout as exc:
|
||||
print('timeout reaching api endpoint')
|
||||
|
|
@ -61,3 +84,6 @@ if __name__ == '__main__':
|
|||
except ujson.JSONDecodeError:
|
||||
print("JSON decode error")
|
||||
sys.exit(-1)
|
||||
finally:
|
||||
if fhandle:
|
||||
fcntl.flock(fhandle, fcntl.LOCK_UN)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ message:reconfigure QFeeds
|
|||
errors:no
|
||||
|
||||
[update]
|
||||
command:/usr/local/opnsense/scripts/qfeeds/qfeedsctl.py update
|
||||
command:/usr/local/opnsense/scripts/qfeeds/qfeedsctl.py -l update
|
||||
parameters:
|
||||
type:script_output
|
||||
message:update QFeeds
|
||||
|
|
|
|||
Loading…
Reference in a new issue