Merge ubuntu-security-tools:iosifache/semgrep-rules-manager into ubuntu-security-tools:master

Proposed by George-Andrei Iosif
Status: Rejected
Rejected by: George-Andrei Iosif
Proposed branch: ubuntu-security-tools:iosifache/semgrep-rules-manager
Merge into: ubuntu-security-tools:master
Diff against target: 199 lines (+87/-7)
6 files modified
audits/.gitignore (+2/-0)
audits/CONTRIBUTING.md (+4/-0)
audits/README.md (+2/-0)
audits/custom-semgrep-rules/third-party/.gitkeep (+0/-0)
audits/uaudit (+78/-6)
audits/workflow.template (+1/-1)
Reviewer Review Type Date Requested Status
Spyros Seimenis Needs Fixing
Review via email: mp+448255@code.launchpad.net

Commit message

Integrates semgrep-rules-manager

Description of the change

This merge proposal targets the auditing capabilities of UST.

As a result of the Semgrep integration in MP #446963 [1], the commits in this merge proposal include a newly constructed Semgrep-related utility, semgrep-rules-manager.

The objective of semgrep-rules-manager [2] is to manage third-party Semgrep rule sources by enabling actions such as downloading, listing, synchronizing, and uninstalling. Beside the open source codebase, there are also a snap [4] and a Python package [5] available.

The merge proposal adds a new workflow:
1. When the first time uaudit is launched, the user is prompted if she wishes to install new Semgrep rules.
2. If yes, the semgrep-rules-manager snap is installed on the local host.
3. Once the installation is complete, all Semgrep rule sources are downloaded to $UST/audits/custom-semgrep-rules/third-party. This allows the user to avoid getting lost in a maze of files by writing her custom rules in the root of $UST/audits/custom-semgrep-rules and having the automatically downloaded ones on $UST/audits/custom-semgrep-rules/third-party.
4. uaudit will then launch Semgrep, which will detect and use the downloaded rules for scanning.

Regardless of the answer supplied in the first step, semgrep-rules-manager can be alternatively launched with the --download-semgrep-rules flag from uaudit.

The commits, in addition to the mentioned behaviour, target documentation files (README.md and CONTRIBUTING.md), which are updated with information about the changes made in this MP.

[1] https://code.launchpad.net/~ubuntu-security/ubuntu-security-tools/+git/ubuntu-security-tools/+merge/446963
[2] https://github.com/iosifache/semgrep-rules-manager
[3] https://snapcraft.io/semgrep-rules-manager
[4] https://pypi.org/project/semgrep-rules-manager

P.S.: The previously generated Semgrep snap is actively utilized by tens of users in our community! The download of semgrep-rules-manager has also begun. So happy about this!

To post a comment you must log in.
Revision history for this message
Spyros Seimenis (sespiros) wrote (last edit ):

I think we can reuse the logic and flow that is already there for tool installation instead of introducing extra helpers. The new requirement of semgrep-rules-manager for example can be handled in verify_requirements() or maybe even better in uaudit_install_dependencies() directly:

```python
def uaudit_install_dependencies():
    dependencies = {}
    for tool in static_analysis_tools:
        dependencies[tool.name] = tool.install_cmd()

+ dependencies["semgrep-rules-manager"] = ["snap", "install", "semgrep-rules-manager"]

    for tool, cmd_args in dependencies.items():
        if is_program_installed(tool):
            debug(f'{tool} is already installed in the system')
        else:
            install_tool(cmd_args, tool)

```

Then we would only need to prompt for the extra sources via ask_for_custom_semgrep_rules() -> download_custom_semgrep_rules() and remove the ensure_installed_semgrep_rules_manager() method.

review: Needs Fixing

Unmerged commits

78b19f8... by George-Andrei Iosif

Updates the documentation with info about semgrep-rules-manager

Signed-off-by: George-Andrei Iosif <email address hidden>

3827dde... by George-Andrei Iosif

Integrates semgrep-rules-manager in uaudit

Signed-off-by: George-Andrei Iosif <email address hidden>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/audits/.gitignore b/audits/.gitignore
2new file mode 100644
3index 0000000..e01805a
4--- /dev/null
5+++ b/audits/.gitignore
6@@ -0,0 +1,2 @@
7+custom-semgrep-rules/third-party/*
8+!custom-semgrep-rules/third-party/.gitkeep
9\ No newline at end of file
10diff --git a/audits/CONTRIBUTING.md b/audits/CONTRIBUTING.md
11index 8d59bfa..7c79d99 100644
12--- a/audits/CONTRIBUTING.md
13+++ b/audits/CONTRIBUTING.md
14@@ -20,3 +20,7 @@
15 ```
16
17 5. If the `summary` member of your `StaticAnalysisTool` object is initialized, its content can be used in reports (e.g. `bug.template` and `workflow.template`) by embedding the `$tool_id>` variable. A frequent usecase is to save the number of created errors and warnings and reference it in the "Static analysis results summary" section of `jira.template`.
18+
19+## Adding Third-party Semgrep Rules
20+
21+Please follow the [contribution guide from `semgrep-rules-manager`](https://github.com/iosifache/semgrep-rules-manager/blob/main/CONTRIBUTING.md#add-a-new-source-with-semgrep-rules).
22diff --git a/audits/README.md b/audits/README.md
23index b34440f..841b25a 100644
24--- a/audits/README.md
25+++ b/audits/README.md
26@@ -18,6 +18,8 @@
27 $ uaudit --download-release=precise hello
28 ```
29
30+If you run `uaudit` for the first time on your system, it will ask if you wish to download additional third-party Semgrep rules. If you intend to scan with Semgrep and opt to download the rules, they will be saved in `./custom-semgrep-rules/third-party`. If you decided not to download them but later changed your mind, execute `uadit --download-semgrep-rules`.
31+
32 Observe the output of `uaudit`. It uses `umt` to download and build source and binary packages. It also creates an `audits` directory that contains all the reports.
33
34 `uaudit` will generate its reports in `<toplevel source>/audits`. You might want to copy these to somewhere safe (eg, `~/ubuntu/security/audits`). Ideas for starting points are in `WORKFLOW.md`. Sift through the various reports, be
35diff --git a/audits/custom-semgrep-rules/third-party/.gitkeep b/audits/custom-semgrep-rules/third-party/.gitkeep
36new file mode 100644
37index 0000000..e69de29
38--- /dev/null
39+++ b/audits/custom-semgrep-rules/third-party/.gitkeep
40diff --git a/audits/uaudit b/audits/uaudit
41index 96d03d2..f3b8aef 100755
42--- a/audits/uaudit
43+++ b/audits/uaudit
44@@ -46,6 +46,9 @@ class StaticAnalysisToolSource(Enum):
45
46 OUTPUT_FILE="$OUTPUT"
47
48+def get_custom_semgrep_rules_location() -> str:
49+ return os.path.join(os.path.dirname(__file__), "custom-semgrep-rules")
50+
51 class StaticAnalysisTool(object):
52 """A class modeling a static analysis tool
53
54@@ -265,7 +268,7 @@ static_analysis_tools = [
55 "--config",
56 "auto",
57 "--config",
58- os.path.join(os.path.dirname(__file__), "custom-semgrep-rules")
59+ get_custom_semgrep_rules_location()
60 ],
61 cmd_txt=["--vim"],
62 cmd_json=["--json"],
63@@ -506,15 +509,21 @@ def uaudit_setup_env():
64
65
66 def query_user_consent_to_install_tool(cmd_args, tool):
67- valid_answers = {"yes": True, "y": True, "no": False, "n": False}
68 command = " ".join(cmd_args)
69 question = f"{tool} is not present in the system.\n" \
70 "The preferred version can be installed by running:\n" \
71 f" {command}\n" \
72 "Do you want to run this now to install it? [y/n] "
73
74+ return ask_question_with_binary_response(question)
75+
76+
77+def ask_question_with_binary_response(question) -> bool:
78+ valid_answers = {"yes": True, "y": True, "no": False, "n": False}
79+
80 while True:
81 sys.stdout.write(question)
82+
83 choice = input().lower()
84 if choice in valid_answers:
85 return valid_answers[choice]
86@@ -538,12 +547,15 @@ def uaudit_install_dependencies():
87 for tool in static_analysis_tools:
88 dependencies[tool.name] = tool.install_cmd()
89 for tool, cmd_args in dependencies.items():
90- rc, out = cmd(['which', tool])
91- if rc != 0:
92- install_tool(cmd_args, tool)
93- else:
94+ if is_program_installed(tool):
95 debug(f'{tool} is already installed in the system')
96+ else:
97+ install_tool(cmd_args, tool)
98
99+def is_program_installed(software_name: str) -> bool:
100+ rc, _ = cmd(['which', software_name])
101+
102+ return (rc == 0)
103
104 def verify_requirements():
105 uaudit_setup_env()
106@@ -1139,6 +1151,55 @@ def create_tags(audit_dir):
107
108 msg("Tags file: %s" % (out_fn_rel))
109
110+def ask_for_custom_semgrep_rules() -> None:
111+ user_not_asked_before = check_create_semgrep_ask_file()
112+ if not user_not_asked_before:
113+ return
114+
115+ question = """\
116+Because Semgrep is built into uaudit for SAST, you can download extra rules to
117+your system to uncover more potential software flaws. Do you wish to install
118+semgrep-rules-manager automatically and download all Semgrep rule sources?
119+[y/n] """
120+
121+ response = ask_question_with_binary_response(question)
122+ if response:
123+ download_custom_semgrep_rules()
124+
125+
126+def check_create_semgrep_ask_file() -> bool:
127+ ask_fn = os.path.join(get_3rd_party_semgrep_rules_location(), ".ask")
128+
129+ if os.path.isfile(ask_fn):
130+ return False
131+
132+ os.mknod(ask_fn)
133+
134+ return True
135+
136+
137+def get_3rd_party_semgrep_rules_location() -> str:
138+ return os.path.join(get_custom_semgrep_rules_location(), "third-party")
139+
140+
141+def download_custom_semgrep_rules() -> None:
142+ ensure_installed_semgrep_rules_manager()
143+
144+ location = get_3rd_party_semgrep_rules_location()
145+
146+ rc, out = cmd(["semgrep-rules-manager", "--dir", location, "download"])
147+ if rc == 0:
148+ msg("The third-party Semgrep rules were downloaded!")
149+ else:
150+ error(f"An error occurred while running semgrep-rules-manager!")
151+
152+
153+def ensure_installed_semgrep_rules_manager() -> None:
154+ if not is_program_installed("semgrep-rules-manager"):
155+ rc, out = cmd(["snap", "install", "semgrep-rules-manager"])
156+ if rc != 0:
157+ error(f"An error occurred while installing semgrep-rules-manager!")
158+
159
160 def get_usage():
161 '''Print usage statement'''
162@@ -1237,6 +1298,11 @@ if __name__ == "__main__":
163 default=False,
164 help="Disable automatic coverity integration via cov-build",
165 action="store_true")
166+ parser.add_argument("--download-semgrep-rules",
167+ dest="download_semgrep_rules",
168+ default=False,
169+ help="Download additonal Semgrep rules and exit",
170+ action="store_true")
171 parser.add_argument("--debug",
172 default=False,
173 help="Print debug output",
174@@ -1264,6 +1330,12 @@ if __name__ == "__main__":
175
176 verify_requirements()
177
178+ if args.download_semgrep_rules:
179+ download_custom_semgrep_rules()
180+ exit()
181+ else:
182+ ask_for_custom_semgrep_rules()
183+
184 if not os.path.exists(args.config):
185 error("Could not find '%s'" % args.config)
186 ust = load_ust_config(args.config)
187diff --git a/audits/workflow.template b/audits/workflow.template
188index 17735f3..c0b6c2a 100644
189--- a/audits/workflow.template
190+++ b/audits/workflow.template
191@@ -74,7 +74,7 @@ the response within the Launchpad MIR bug.
192 ### CVE History
193
194 - Run $UCT/scripts/pkg_history $package.
195-- Run $UCT/scripts/pkg_status $package
196+- Run $UCT/scripts/pkg_status $package.
197 - If there are old CVEs,
198 - What were they?
199 - Were they fixed in a timely fashion?

Subscribers

People subscribed via source and target branches