Skip to content

Commit

Permalink
ZAP import accepts types other than "url"
Browse files Browse the repository at this point in the history
config:

```
importUrlsFromFile:
  type: one of 'har', 'modsec2', 'url' (default), 'zap_messages'
  fileName: path to file
```
  • Loading branch information
Your Name committed Dec 6, 2024
1 parent 386fab1 commit aa4583a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 12 deletions.
6 changes: 4 additions & 2 deletions config/config-template-zap-long.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ scanners:
apiUrl: "<URL to openAPI>"
# alternative to apiURL: apiFile: "<local path to openAPI file>"

# A list of URLs can also be provided, from a text file (1 URL per line)
importUrlsFromFile: "<path to import URL>"
# A list of URLs can also be provided, type supported: 'har', 'modsec2', 'url' (default), 'zap_messages'
importUrlsFromFile:
type: "url"
fileName: "<path to import URL>"

graphql:
endpoint: "<URL to GraphQL API endpoint>"
Expand Down
44 changes: 36 additions & 8 deletions scanners/zap/zap.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,17 +376,45 @@ def _setup_zap_automation(self):

def _setup_import_urls(self):
"""If importUrlsFromFile exists:
prepare an import job for URLs importUrlsFromFile _must_ be an existing file on the host
Its content is a text file: a list of GET URLs, each of which will be scanned
Prepare a URL import job. All ZAP's import job are supported: 'har', 'modsec2', 'url' (default), 'zap_messages'
2 possibilities:
1- [for backward compatibility] if importUrlsFromFile is a string:
it must point to an existing file on the host
2- importUrlsFromFile is a dictionary: { "type": "<type>", "fileName": "<path/to/file>"}
The filename of the import will always be copied in the `container_work_dir` as importUrls.txt
"""
job = {"name": "import", "type": "import", "parameters": {"type": "url"}}
# Basic job config. The `type` parameter will be set later
job = {"name": "import", "type": "import", "parameters": {"fileName": f"{self.container_work_dir}/importUrls.txt"}}

types = ('har', 'modsec2', 'url', 'zap_messages')

source = "" # Location of the import file on the host

orig = self.my_conf("importUrlsFromFile")
if not orig:
conf = self.my_conf("importUrlsFromFile")
if not conf:
return
dest = f"{self.container_work_dir}/importUrls.txt"
self._include_file(orig, dest)
job["parameters"]["fileName"] = dest
if isinstance(conf, str):
# Backward compatibility with previous behavior
source = conf
job["parameters"]["type"] = "url"

elif isinstance(conf, dict):
# "importUrlsFromFile" = { type, fileName }
source = self.my_conf("importUrlsFromFile.fileName")
if not source:
raise ValueError("ZAP config error: importUrlsFromFile must have a `fileName` entry")
job["parameters"]["type"] = self.my_conf("importUrlsFromFile.type", "url")

else:
raise ValueError("ZAP config error: importUrlsFromFile must be a dictionary")

if not job["parameters"]["type"] in types:
raise ValueError(f"ZAP config error: importUrlsFromFile.type must be within {types}")

self._include_file(source, job["parameters"]["fileName"])
self.automation_config["jobs"].append(job)

def _setup_export_site_tree(self):
Expand Down
39 changes: 37 additions & 2 deletions tests/scanners/zap/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,47 @@ def test_setup_authentication_auth_rtoken_preauth(test_config):


def test_setup_import_urls(test_config):
# trick: set this very file as import
test_config.set("scanners.zap.importUrlsFromFile", __file__)
# trick: use is the current pytest as import file

# 1- Test backward compatible behaviour
test_config.set("scanners.zap.importUrlsFromFile", __file__)
test_zap = ZapNone(config=test_config)
test_zap.setup()
assert Path(test_zap.host_work_dir, "importUrls.txt").is_file()
for item in test_zap.automation_config["jobs"]:
if item["type"] == "import":
assert item["parameters"]["type"] == "url"
break
else:
assert False

# 2- Test new config style, with type "har"
test_config.set("scanners.zap.importUrlsFromFile", {"type": "har", "fileName": __file__})
test_zap = ZapNone(config=test_config)
test_zap.setup()
for item in test_zap.automation_config["jobs"]:
if item["type"] == "import":
assert item["parameters"]["type"] == "har"
break
else:
assert False

# 3- Test new config style, defaulting to "url" type
test_config.set("scanners.zap.importUrlsFromFile", {"fileName": __file__})
test_zap = ZapNone(config=test_config)
test_zap.setup()
for item in test_zap.automation_config["jobs"]:
if item["type"] == "import":
assert item["parameters"]["type"] == "url"
break
else:
assert False

# 4- Test new config style, with an unexisting type
test_config.set("scanners.zap.importUrlsFromFile", {"type": "doesntexist", "fileName": __file__})
test_zap = ZapNone(config=test_config)
with pytest.raises(ValueError) as exc:
test_zap.setup()


def test_setup_exclude_urls(test_config):
Expand Down

0 comments on commit aa4583a

Please sign in to comment.