Skip to content

Commit bc20a28

Browse files
merging falco integration
2 parents 597f9f4 + 646f506 commit bc20a28

File tree

11 files changed

+683
-382
lines changed

11 files changed

+683
-382
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
build
44
dist
55
*.egg-info
6-
__pycache__
6+
__pycache__
7+
test.py
8+
*.json

README.md

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# scsctl
2+
23
> We are continuously adding the listed features
34
45
CLI/CI Tool for Automating Vulnerability Management for Enhancing Software Supply Chain Security Measures.
56

67
### Features
8+
79
- Integration with other Tools & Platforms:
810
- Trivy
911
- Grype
@@ -24,8 +26,8 @@ CLI/CI Tool for Automating Vulnerability Management for Enhancing Software Suppl
2426
- Docker Build tool
2527
- Renovate
2628
- Integration with DB(s):
27-
- ClickHouse
28-
- Cassandra
29+
- ClickHouse
30+
- Cassandra
2931
- Reports: (dependency packages and SBOM/gitbom reports)
3032
- SBOM
3133
- Report using Profiling tools Data
@@ -81,15 +83,17 @@ Before starting, make sure you have the following installed and configured:
8183
2. Trivy - Trivy will be automatically installed if not present
8284
3. Pyroscope - Pyroscope is up and running, and profiling data is being collected from the application you want to scan. You also need the Pyroscope server URL and the application name
8385
4. ClickHouse (optional) - If you want to save the data collected by SCSCTL for historical analysis purpose, then make sure ClickHouse is up and running and you have the ClickHouse server URL and the database details
84-
> If you don't want to save the data, then you can skip this step.
85-
86-
> If you want to save the data, then please set the following environment variables:
87-
The database name will be `scsctl`
88-
> - `CLICKHOUSE_HOST` - The URL of the ClickHouse server
89-
> - `CLICKHOUSE_USER` - The username of the ClickHouse server
90-
> - `CLICKHOUSE_PASSWORD` - The password of the ClickHouse server
91-
> - `CLICKHOUSE_PORT` - The port of the ClickHouse server
92-
86+
87+
> If you don't want to save the data, then you can skip this step.
88+
89+
> If you want to save the data, then please set the following environment variables:
90+
> The database name will be `scsctl`
91+
>
92+
> - `CLICKHOUSE_HOST` - The URL of the ClickHouse server
93+
> - `CLICKHOUSE_USER` - The username of the ClickHouse server
94+
> - `CLICKHOUSE_PASSWORD` - The password of the ClickHouse server
95+
> - `CLICKHOUSE_PORT` - The port of the ClickHouse server
96+
9397
### Running the tool
9498

9599
1. Clone the repo
@@ -100,19 +104,47 @@ Before starting, make sure you have the following installed and configured:
100104
6. You can also run the tool using `python app.py` without building the wheel file
101105
7. After scanning, you can see the reports or rebuild the docker image from the menu
102106

103-
104107
### Commands
105108

106109
scsctl has the following commands:
110+
111+
- pyroscope_app_name (string) - Pyroscope app name
112+
- docker_image_name (string) - Docker image name
113+
- pyroscope_url (string) - Url for pyroscope
114+
- falco_pod_name (string) - Pod name of falco
115+
- falco_target_deployment_name (string) - Deployment name of falco
116+
- db_enabled (boolean) - To enable db saving
117+
- falco_enabled (boolean) (optional) - To get logs from falco
118+
- docker_file_folder_path (string) (optional) - Dockerfile folder path if you need to rebuild the image
119+
- config_file (optional) (YAML)
120+
107121
> This command will scan the docker image and generate the reports
122+
108123
```shell
109-
scsctl scan --docker_image_name <docker-image-name> --docker_file_folder_path <docker-file-folder-path> --pyroscope_url <pyroscope-url> --pyroscope_app_name <pyroscope-app-name>
124+
scsctl scan --pyroscope_app_name <pyroscope_app_name> --docker_image_name <docker_image_name> --pyroscope_url <pyroscope_url> --docker_file_folder_path <docker_file_folder_path> --falco_pod_name <falco_pod_name> --falco_target_deployment_name <app> --falco_enabled
110125
```
126+
111127
Example:
128+
129+
```shell
130+
scsctl scan --pyroscope_app_name dagflow-api --docker_image_name dagflow-app-with-db-url:latest --pyroscope_url http://localhost:4040 --docker_file_folder_path /home/jegath/Documents/intelops/sps/dagflow/app/ --falco_pod_name falco-mvnmt --falco_target_deployment_name app --falco_enabled
131+
```
132+
133+
> There is also an option to pass a yaml as a config file.
134+
112135
```shell
113-
scsctl scan --docker_image_name test:latest --docker_file_folder_path /home/test --pyroscope_url http://localhost:4040 --pyroscope_app_name test
136+
scsctl scan --config_file ./test.yaml
114137
```
115138

116-
--------------------------------------------------
117-
## Inform security issues of this project:
118-
[Security](SECURITY.md )
139+
> Sample yaml file
140+
141+
```yaml
142+
pyroscope_app_name: dagflow-api
143+
docker_image_name: dagflow-app-with-db-url:latest
144+
pyroscope_url: http://localhost:4040
145+
falco_pod_name: falco-mvnmt
146+
falco_target_deployment_name: app
147+
db_enabled: true
148+
falco_enabled: true
149+
docker_file_folder_path: /home/jegath/Documents/intelops/sps/dagflow/app/
150+
```

app.py

Lines changed: 148 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,185 @@
11
from datetime import datetime
2-
from helper import get_sbom_report, get_pyroscope_data, AppDetails,compare_and_find_extra_packages,print_sbom_report, print_pyroscope_packages, custom_style_fancy,modify_and_build_docker_image, save_sbom_data, save_pyroscope_data
32
import click
43
import questionary
4+
from helper.falco import (
5+
parse_logs_and_get_package_paths,
6+
compare_and_find_extra_packages_using_falco,
7+
print_falco_packages,
8+
save_falco_data,
9+
)
10+
from helper.pyroscope import (
11+
get_pyroscope_data,
12+
print_pyroscope_packages,
13+
save_pyroscope_data,
14+
compare_and_find_pyroscope_extra_packages,
15+
)
16+
from helper.common import AppDetails, generate_final_report, modify_and_build_docker_image, custom_style_fancy
17+
from helper.trivy import get_sbom_report, print_sbom_report, save_sbom_data
18+
19+
import yaml
520

621

722
@click.group()
823
def cli():
924
pass
1025

26+
1127
current_datetime = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
1228
batch_id = f"scsctl_{current_datetime}"
1329

1430

1531
@click.command()
16-
@click.option('--pyroscope_app_name', prompt='Enter pyroscope app name', help='Name of the pyroscope app')
17-
@click.option('--docker_image_name', prompt='Enter docker image name', help='Name of the docker image')
18-
@click.option('--pyroscope_url', prompt='Enter pyroscope url', help='Url of the pyroscope app')
19-
@click.option('--docker_file_folder_path', help='Path of the docker file to rebuild', default=None, is_flag=False, flag_value=None)
20-
def scan(pyroscope_app_name,docker_image_name,pyroscope_url, docker_file_folder_path = None):
32+
@click.option("--pyroscope_app_name", default=None, help="Name of the pyroscope app")
33+
@click.option("--docker_image_name", default=None, help="Name of the docker image")
34+
@click.option("--pyroscope_url", default=None, help="Url of the pyroscope app")
35+
@click.option(
36+
"--falco_pod_name",
37+
default=None,
38+
help="Falco pod name",
39+
is_flag=False,
40+
flag_value=None,
41+
)
42+
@click.option(
43+
"--falco_target_deployment_name",
44+
default=None,
45+
help="Deployment name of the falco target",
46+
is_flag=False,
47+
flag_value=None,
48+
)
49+
@click.option("--db_enabled", help="Enable db", default=False, is_flag=True, flag_value=True)
50+
@click.option("--falco_enabled", help="Enable falco", default=False, is_flag=True, flag_value=True)
51+
@click.option(
52+
"--docker_file_folder_path", help="Path of the docker file to rebuild", default=None, is_flag=False, flag_value=None
53+
)
54+
@click.option("--config_file", help="Path of the configuration file", default=None, is_flag=False, flag_value=None)
55+
def scan(
56+
pyroscope_app_name=None,
57+
docker_image_name=None,
58+
pyroscope_url=None,
59+
falco_pod_name=None,
60+
falco_target_deployment_name=None,
61+
docker_file_folder_path=None,
62+
db_enabled=False,
63+
falco_enabled=False,
64+
config_file=None,
65+
):
66+
config_data = {}
67+
if config_file is not None:
68+
with open(config_file, "r") as f:
69+
config_data = yaml.safe_load(f)
70+
71+
# If command line options are not provided, take the options from the configuration file
72+
if pyroscope_app_name is None:
73+
pyroscope_app_name = config_data.get("pyroscope_app_name")
74+
if docker_image_name is None:
75+
docker_image_name = config_data.get("docker_image_name")
76+
if pyroscope_url is None:
77+
pyroscope_url = config_data.get("pyroscope_url")
78+
if falco_pod_name is None:
79+
falco_pod_name = config_data.get("falco_pod_name")
80+
if falco_target_deployment_name is None:
81+
falco_target_deployment_name = config_data.get("falco_target_deployment_name")
82+
if docker_file_folder_path is None:
83+
docker_file_folder_path = config_data.get("docker_file_folder_path")
84+
85+
# For flags, only set from config if not set from command line
86+
if not db_enabled:
87+
db_enabled = config_data.get("db_enabled", False)
88+
if not falco_enabled:
89+
falco_enabled = config_data.get("falco_enabled", False)
90+
91+
# Check mandatory fields
92+
if pyroscope_app_name is None:
93+
raise ValueError("pyroscope_app_name is required, either via command line or config file")
94+
95+
if docker_image_name is None:
96+
raise ValueError("docker_image_name is required, either via command line or config file")
97+
98+
if pyroscope_url is None:
99+
raise ValueError("pyroscope_url is required, either via command line or config file")
100+
if falco_enabled and (falco_pod_name is None or falco_target_deployment_name is None):
101+
raise ValueError(
102+
"falco_pod_name and falco_target_deployment_name are required, either via command line or config file if falco is enabled"
103+
)
104+
21105
"""This script will scan the docker image and find the unused packages"""
22-
appDetails = AppDetails(pyroscope_app_name=pyroscope_app_name,docker_image_name=docker_image_name,pyroscope_url=pyroscope_url)
106+
appDetails = AppDetails(
107+
pyroscope_app_name=pyroscope_app_name, docker_image_name=docker_image_name, pyroscope_url=pyroscope_url
108+
)
23109

24110
scan_status = True
25111
sbom_report, sbom_status = get_sbom_report(appDetails)
26-
if(sbom_status):
112+
if sbom_status:
27113
pyroscope_data, pyroscope_status = get_pyroscope_data(appDetails)
28-
if(pyroscope_status):
29-
final_report, extra_packages = compare_and_find_extra_packages(pyroscope_data,sbom_report)
30-
save_sbom_data(sbom_data=sbom_report,batch_id=batch_id)
31-
save_pyroscope_data(pyroscope_data=pyroscope_data,batch_id=batch_id)
114+
if pyroscope_status:
115+
pyroscope_found_extra_packages = compare_and_find_pyroscope_extra_packages(
116+
pyroscope_package_names=pyroscope_data,
117+
sbom_package_names=sbom_report,
118+
)
119+
if falco_enabled:
120+
falco_package_paths, falco_status = parse_logs_and_get_package_paths(
121+
falco_pod_name=falco_pod_name, target_deployment_name=falco_target_deployment_name
122+
)
123+
if falco_status:
124+
falco_found_extra_packages = compare_and_find_extra_packages_using_falco(
125+
falco_package_paths, sbom_report
126+
)
127+
final_report = generate_final_report(
128+
sbom_package_names=sbom_report,
129+
pyroscope_package_names=pyroscope_found_extra_packages,
130+
falco_found_extra_packages=falco_found_extra_packages,
131+
)
132+
else:
133+
final_report = generate_final_report(
134+
sbom_package_names=sbom_report, pyroscope_package_names=pyroscope_found_extra_packages
135+
)
136+
if db_enabled:
137+
save_sbom_data(sbom_data=sbom_report, batch_id=batch_id)
138+
save_pyroscope_data(pyroscope_data=pyroscope_data, batch_id=batch_id)
139+
if falco_enabled:
140+
save_falco_data(falco_data=falco_found_extra_packages, batch_id=batch_id)
141+
32142
else:
33143
scan_status = False
34144
click.echo("\nError fetching data from pyroscope... Exiting")
35145
else:
36146
scan_status = False
37147
click.echo("\nError fetching data from sbom_report... Exiting")
38148

39-
choices = ['Sbom report', 'Pyroscope detected packages', 'Final report', "Rebuild the image",'Exit']
149+
choices = [
150+
"Sbom report",
151+
"Pyroscope detected packages",
152+
"Falco detected packages",
153+
"Final report",
154+
"Rebuild the image",
155+
"Exit",
156+
]
40157

41-
if(scan_status):
158+
if falco_enabled == False:
159+
choices.remove("Falco detected packages")
160+
161+
if scan_status:
42162
while True:
43-
choice = questionary.select('Select an option', choices=choices,style=custom_style_fancy).ask()
44-
if choice == 'Exit':
45-
break;
46-
if choice == 'Sbom report':
163+
choice = questionary.select("Select an option", choices=choices, style=custom_style_fancy).ask()
164+
if choice == "Exit":
165+
break
166+
if choice == "Sbom report":
47167
print_sbom_report(sbom_report)
48-
if choice == 'Pyroscope detected packages':
168+
if choice == "Pyroscope detected packages":
49169
print_pyroscope_packages(pyroscope_data)
50-
if choice == 'Final report':
170+
if choice == "Falco detected packages":
171+
print_falco_packages(falco_found_extra_packages)
172+
if choice == "Final report":
51173
click.echo("Vulnerable packages that can be uninstalled from the docker image are:")
52174
click.echo(final_report)
53-
if choice == 'Rebuild the image':
54-
if(docker_file_folder_path == None):
55-
docker_file_folder_path = click.prompt('Enter docker file folder path', type=str)
56-
modify_and_build_docker_image(docker_file_folder_path, extra_packages, batch_id)
175+
if choice == "Rebuild the image":
176+
if docker_file_folder_path == None:
177+
docker_file_folder_path = click.prompt("Enter docker file folder path", type=str)
178+
modify_and_build_docker_image(docker_file_folder_path, pyroscope_found_extra_packages, batch_id)
179+
57180

58181
cli.add_command(scan)
59182

60183

61-
if __name__ == '__main__':
184+
if __name__ == "__main__":
62185
cli()

0 commit comments

Comments
 (0)