Passed
Push — master ( 6525cc...6b94a1 )
by -
01:42
created

deact()   A

Complexity

Conditions 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0466
Metric Value
cc 4
dl 0
loc 18
rs 9.2
ccs 12
cts 14
cp 0.8571
crap 4.0466
1 1
import logging
2 1
import re
3 1
import string
4 1
from time import time, localtime, strftime
5
6 1
from flask import Blueprint, render_template, request, redirect, flash, Response
1 ignored issue
show
Configuration introduced by
The import flask could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 1
from sqlalchemy.exc import SQLAlchemyError
0 ignored issues
show
Configuration introduced by
The import sqlalchemy.exc could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8
9 1
from spike.model import db
10 1
from spike.model.naxsi_rules import NaxsiRules
11 1
from spike.model.naxsi_rulesets import NaxsiRuleSets
12 1
from spike.model import naxsi_mz, naxsi_score
13
14 1
rules = Blueprint('rules', __name__)
15
16
17 1
@rules.route("/")
18
def index():
19 1
    _rules = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).all()
20 1
    if not _rules:
21
        flash("no rules found, please create one", "success")
22
        return redirect("/rules/new")
23 1
    return render_template("rules/index.html", rules=_rules)
24
25
26 1
@rules.route("/plain/<int:sid>", methods=["GET"])
27
def plain(sid):
28 1
    _rule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
29 1
    if not _rule:
30 1
        flash("no rules found, please create one", "error")
31 1
        return redirect("/rules/new")
32
33 1
    return Response(__get_textual_representation_rule(_rule), mimetype='text/plain')
34
35
36 1
@rules.route("/view/<int:sid>", methods=["GET"])
37
def view(sid):
38 1
    _rule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
39 1
    if _rule is None:
40 1
        flash("no rules found, please create one", "error")
41 1
        return redirect("/rules/")
42
43 1
    return render_template("rules/view.html", rule=_rule, rtext=__get_textual_representation_rule(_rule, full=0))
44
45
46 1
@rules.route("/select/<path:selector>", methods=["GET"])
47 1
def select(selector=''):
48
    if not selector:
49
        return redirect("/rules/")
50
51
    sel = str(selector)
52
    logging.info("sel: %s ", sel)
53
    try:
54
        rs_val = sel.split(":")[1]
55
    except SQLAlchemyError:
56
        return redirect("/rules/")
57
58
    if sel.startswith('r:'):
59
        _rules = NaxsiRules.query.filter(NaxsiRules.ruleset == rs_val).order_by(NaxsiRules.sid.desc()).all()
60
        selection = "Search ruleset: %s " % rs_val
61
    elif sel.startswith('id:'):
62
        _rules = NaxsiRules.query.filter(NaxsiRules.sid == rs_val).order_by(NaxsiRules.sid.desc()).all()
63
        selection = "Search sid: %s " % rs_val
64
    else:
65
        return redirect("/rules/")
66
67
    return render_template("rules/index.html", rules=_rules, selection=selection)
68
69
70 1
@rules.route("/search/", methods=["GET"])
71
def search():
72 1
    terms = request.args.get('s', '')
73
74 1
    if len(terms) < 2:
75 1
        return redirect('/rules')
76
77
    # No fancy injections
78 1
    whitelist = set(string.ascii_letters + string.digits + ':-_ ')
79 1
    filtered = ''.join(filter(whitelist.__contains__, terms))
80
81 1
    if filtered.isdigit():  # get rule by id
82 1
        _rules = db.session.query(NaxsiRules).filter(NaxsiRules.sid == int(filtered)).all()
83
    else:
84 1
        expression = '%' + filtered + '%'
85 1
        _rules = db.session.query(NaxsiRules).filter(
86
            db.or_(
87
                NaxsiRules.msg.like(expression),
88
                NaxsiRules.rmks.like(expression),
89
                NaxsiRules.detection.like(expression)
90
            )
91
        ).order_by(NaxsiRules.sid.desc()).all()
92 1
    return render_template("rules/index.html", rules=_rules, selection="Search: %s" % filtered, lsearch=terms)
93
94
95 1
@rules.route("/new", methods=["GET", "POST"])
96
def new():
97 1
    latest_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
98 1
    if latest_sid is None:
99
        sid = 200001
100
    else:
101 1
        sid = latest_sid.sid + 1
102
103 1
    if request.method == "GET":
104 1
        _rulesets = NaxsiRuleSets.query.all()
105 1
        return render_template("rules/new.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, latestn=sid)
106
107
    # create new rule
108 1
    logging.debug('Posted new request: %s', request.form)
109
110 1
    detect = str(request.form["detection"]).strip()
111 1
    if not detect.startswith("str:") and not detect.startswith("rx:"):
112 1
        detect = "str:%s" % detect
113
114 1
    mz = "|".join(request.form.getlist("mz"))
115
116 1
    try:
117 1
        if request.form["custom_mz"] == "on":
118
            mz = "%s|%s" % (mz, request.form["custom_mz_val"])
119 1
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
120 1
        pass
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
121
122 1
    score_raw = request.form["score"].strip()
123 1
    score_val = request.form["score_%s" % score_raw].strip()
124 1
    score = "%s:%s" % (score_raw, score_val)
125 1
    rmks = request.form["rmks"]
126 1
    ruleset = request.form["ruleset"]
127 1
    negative = 'negative' in request.form and request.form['negative'] == 'checked'
128
129 1
    nrule = NaxsiRules(request.form["msg"], detect, mz, score, sid, ruleset, rmks, "1", negative, int(time()))
130 1
    db.session.add(nrule)
131
132 1
    try:
133 1
        db.session.commit()
134 1
        flash("OK: created %s : %s" % (sid, request.form["msg"]), "success")
135 1
        return redirect("/rules/edit/%s" % sid)
136
    except SQLAlchemyError:
137
        flash("ERROR while trying to create %s : %s" % (sid, request.form["msg"]), "error")
138
139
    return redirect("/rules/new")
140
141
142 1
@rules.route("/edit/<path:sid>", methods=["GET", "POST"])
143
def edit(sid):
144 1
    rinfo = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
145 1
    if not rinfo:
146 1
        return redirect("/rules/")
147
148 1
    _rulesets = NaxsiRuleSets.query.all()
149 1
    rruleset = NaxsiRuleSets.query.filter(NaxsiRuleSets.name == rinfo.ruleset).first()
150 1
    custom_mz = ""
151 1
    mz_check = rinfo.mz
152 1
    if re.search(r"^\$[A-Z]+:(.*)\|[A-Z]+", mz_check):
153
        custom_mz = mz_check
154
        rinfo.mz = "custom"
155 1
    return render_template("rules/edit.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, rules_info=rinfo,
156
                           rule_ruleset=rruleset, custom_mz=custom_mz)
157
158
159 1
@rules.route("/save/<path:sid>", methods=["POST"])
160
def save(sid):  # FIXME this is the exact same method as the `new` one.
161
162
    # create new rule
163
    try:
164
        msg = request.form["msg"]
165
        detect = str(request.form["detection"]).strip()
166
        if not detect.startswith("str:") and not detect.startswith("rx:"):
167
            detect = "str:%s" % detect
168
        mz = "|".join(request.form.getlist("mz"))
169
        try:
170
            if request.form["custom_mz"] == "on":
171
                if len(mz) > 1:
172
                    mz = "%s|%s" % (request.form["custom_mz_val"], mz)
173
                else:
174
                    mz = "%s" % (request.form["custom_mz_val"])
175
        except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
176
            pass
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
177
        score_raw = request.form["score"].strip()
178
        score_val = request.form["score_%s" % score_raw].strip()
179
        score = "%s:%s" % (score_raw, score_val)
180
        # sid = nr["sid"]
181
        rmks = request.form["rmks"]
182
        ruleset = request.form["ruleset"]
183
        active = request.form["active"]
184
        negative = 'negative' in request.form and request.form['negative'] == 'checked'
185
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
186
        flash('ERROR - please select MZ/Score <a href="javascript:alert(history.back)">Go Back</a>', "error")
187
        return redirect("/rules/edit/%s" % sid)
188
189
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
190
    nrule.msg = msg
191
    nrule.detection = detect
192
    nrule.mz = mz
193
    nrule.score = score
194
    nrule.ruleset = ruleset
195
    nrule.rmks = rmks
196
    nrule.active = active
197
    nrule.negative = negative
198
    nrule.timestamp = int(time())
199
    db.session.add(nrule)
200
    try:
201
        db.session.commit()
202
    except SQLAlchemyError:
203
        flash("ERROR while trying to update %s : %s" % (sid, msg), "error")
204
    return redirect("/rules/edit/%s" % sid)
205
206
207 1
@rules.route("/del/<path:sid>", methods=["GET"])
208 1
def del_sid(sid=''):
209 1
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
210 1
    if not nrule:
211 1
        return redirect("/rules/")
212
213 1
    db.session.delete(nrule)
214 1
    try:
215 1
        db.session.commit()
216 1
        flash("OK: deleted %s : %s" % (sid, nrule.msg), "success")
217
    except SQLAlchemyError:
218
        flash("ERROR while trying to update %s : %s" % (sid, nrule.msg), "error")
219
220 1
    return redirect("/rules/")
221
222
223 1
@rules.route("/deact/<int:sid>", methods=["GET"])
224
def deact(sid):
225 1
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
226 1
    if nrule is None:
227 1
        return redirect("/rules/")
228
229 1
    fm = 'deactivate' if nrule.active else 'reactivate'
230 1
    nrule.active = not nrule.active
231
232 1
    db.session.add(nrule)
233 1
    try:
234 1
        db.session.commit()
235 1
        flash("OK: %s %sd : %s" % (fm, sid, nrule.msg), "success")
236
    except SQLAlchemyError:
237
        flash("ERROR while trying to %s %s : %s" % (fm, sid, nrule.msg), "error")
238
239 1
    _rulesets = NaxsiRuleSets.query.all()
240 1
    return render_template("rules/edit.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, rules_info=nrule)
241
242
243 1
def __get_textual_representation_rule(rule, full=1):
0 ignored issues
show
Coding Style Naming introduced by
The name __get_textual_representation_rule does not conform to the function naming conventions ([a-z_][a-z0-9_]{1,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
244 1
    rdate = strftime("%F - %H:%M", localtime(float(str(rule.timestamp))))
245 1
    rmks = "# ".join(rule.rmks.strip().split("\n"))
246 1
    detect = rule.detection.lower() if rule.detection.startswith("str:") else rule.detection
247 1
    negate = 'negative' if rule.negative == 1 else ''
248
249 1
    if full == 1:
250 1
        nout = """
251
#
252
# sid: %s | date: %s
253
#
254
# %s
255
#
256
MainRule %s "%s" "msg:%s" "mz:%s" "s:%s" id:%s ;
257
258
""" % (rule.sid, rdate, rmks, negate, detect, rule.msg, rule.mz, rule.score, rule.sid)
259
    else:
260 1
        nout = """MainRule %s "%s" "msg:%s" "mz:%s" "s:%s" id:%s  ;""" % \
261
               (negate, rule.detection, rule.msg, rule.mz, rule.score, rule.sid)
262
263
    return nout
264