8000 chore: use python only by fzipi · Pull Request #2 · coreruleset/crs-linter · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

chore: use python only #2

8000
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ The `ctl:auditLogParts=+E` (or any kind of `ctl:auditLogParts`) is not allowed i
See the CRS PR [#3034](https://github.com/coreruleset/coreruleset/pull/3034)

```
$ util/crs-rules-check/rules-check.py -r util/crs-rules-check/examples/test6.conf
crs-linter -r util/crs-rules-check/examples/test6.conf
Config file: util/crs-rules-check/examples/test6.conf
Parsing ok.
Ignore case check ok.
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ packages = [

# Requirements
dependencies = [
"msc_pyparser >=1.2.1"
"msc_pyparser >=1.2.1",
"dulwich (>=0.22.7,<0.23.0)",
"semver (>=3.0.2,<4.0.0)"
]

[project.scripts]
Expand Down
63 changes: 37 additions & 26 deletions src/crs_linter/cli.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#!/usr/bin/env python3
import logging
import subprocess
import pathlib
import sys
import msc_pyparser
import difflib
import argparse
import re
from crs_linter.linter import Check
from dulwich import porcelain
from dulwich.repo import Repo
from dulwich.contrib.release_robot import get_current_version, get_recent_tags
from semver import Version

from crs_linter.linter import Check

oformat = "native"

Expand All @@ -17,24 +21,30 @@ def errmsg(msg):
else:
print(msg)


def errmsgf(msg):
if oformat == "github":
if 'message' in msg and msg['message'].strip() != "":
print("::error%sfile={file},line={line},endLine={endLine},title={title}:: {message}".format(**msg) % (msg['indent']*" "))
print("::error%sfile={file},line={line},endLine={endLine},title={title}:: {message}".format(**msg) % (
msg['indent'] * " "))
else:
print("::error%sfile={file},line={line},endLine={endLine},title={title}::".format(**msg) % (msg['indent']*" "))
print("::error%sfile={file},line={line},endLine={endLine},title={title}::".format(**msg) % (
msg['indent'] * " "))
else:
if 'message' in msg and msg['message'].strip() != "":
print("%sfile={file}, line={line}, endLine={endLine}, title={title}: {message}".format(**msg) % (msg['indent']*" "))
print("%sfile={file}, line={line}, endLine={endLine}, title={title}: {message}".format(**msg) % (
msg['indent'] * " "))
else:
print("%sfile={file}, line={line}, endLine={endLine}, title={title}".format(**msg) % (msg['indent']*" "))
print("%sfile={file}, line={line}, endLine={endLine}, title={title}".format(**msg) % (msg['indent'] * " "))


def msg(msg):
if oformat == "github":
print("::debug::%s" % (msg))
else:
print(msg)


def remove_comments(data):
"""
In some special cases, remove the comments from the beginning of the lines.
Expand Down Expand Up @@ -75,8 +85,8 @@ def remove_comments(data):
"""
_data = [] # new structure by lines
lines = data.split("\n")
marks = re.compile("^#(| *)(SecRule|SecAction)", re.I) # regex what catches the rules
state = 0 # hold the state of the parser
marks = re.compile("^#(| *)(SecRule|SecAction)", re.I) # regex what catches the rules
state = 0 # hold the state of the parser
for l in lines:
# if the line starts with #SecRule, #SecAction, # SecRule, # SecAction, set the marker
if marks.match(l):
Expand All @@ -95,32 +105,33 @@ def remove_comments(data):

return data

def generate_version_string():

def generate_version_string(directory):
"""
generate version string from git tag
program calls "git describe --tags" and converts it to version
eg:
v4.5.0-6-g872a90ab -> "4.6.0-dev"
v4.5.0-0-abcd01234 -> "4.5.0"
"""
result = subprocess.run(["git", "describe", "--tags", "--match", "v*.*.*"], capture_output=True, text=True)
version = re.sub("^v", "", result.stdout.strip())
print(f"Latest tag found: {version}")
ver, commits = version.split("-")[0:2]
if int(commits) > 0:
version = ver.split(".")
version[1] = str((int(version[1]) + 1))
ver = f"""{".".join(version)}-dev"""
return ver

current_version = Version.parse(get_current_version(projdir=str(directory.resolve())))
next_minor = current_version.bump_minor()
version = next_minor.replace(prerelease="dev")
print(version)

return f"OWASP_CRS/{version}"


def main():
logger = logging.getLogger(__name__)
parser = argparse.ArgumentParser(description="CRS Rules Check tool")
parser.add_argument("-o", "--output", dest="output", help="Output format native[default]|github", required=False)
parser.add_argument("-d", "--directory", dest="directory", type=pathlib.Path,
help='Directory path to CRS git repository', required=False)
parser.add_argument("-r", "--rules", metavar='/path/to/coreruleset/*.conf', type=str,
nargs='*', help='Directory path to CRS rules', required=True,
action="append")
nargs='*', help='Directory path to CRS rules', required=True,
action="append")
parser.add_argument("-t", "--tags-list", dest="tagslist", help="Path to file with permitted tags", required=True)
parser.add_argument("-v", "--version", dest="version", help="Version string", required=False)
args = parser.parse_args()
Expand All @@ -136,7 +147,7 @@ def main():

if args.version is None:
# if no --version/-v was given, get version from git describe --tags output
crsversion = generate_version_string()
crsversion = generate_version_string(args.directory)
else:
crsversion = args.version.strip()
# if no "OWASP_CRS/" prefix, append it
Expand Down Expand Up @@ -208,7 +219,7 @@ def main():
for f in parsed_structs.keys():

msg(f)
c = Check(parsed_structs[f], txvars)
c = Check(parsed_structs[f], f, txvars)

### check case usings
c.check_ignore_case()
Expand Down Expand Up @@ -301,7 +312,7 @@ def main():
# this method collects the TX variables, which set via a
# `setvar` action anywhere
# this method does not check any mandatory clause
c.collect_tx_variable(f)
c.collect_tx_variable()

### check duplicate ID's
# c.dupes filled during the tx variable collected
Expand Down Expand Up @@ -340,7 +351,7 @@ def main():
retval = 1

### check existence of used TX variables
c.check_tx_variable(f)
c.check_tx_variable()
if len(c.undef_txvars) == 0:
msg(" All TX variables are set.")
else:
Expand All @@ -352,7 +363,7 @@ def main():
errmsgf(a)
retval = 1
### check new unlisted tags
c.check_tags(f, tags)
c.check_tags(tags)
if len(c.newtags) == 0:
msg(" No new tags added.")
else:
Expand Down Expand Up @@ -434,4 +445,4 @@ def main():


if __name__ == "__main__":
main()
main()
Loading
Loading
0