pyfsr.exports¶
Read and validate FortiSOAR Export Wizard bundles – offline, no appliance needed.
A FortiSOAR .zip comes in two flavours that share one payload format:
a configuration export –
info.jsoncarriesexported_from/exported_byand nothing that names the bundle. It installs throughimport_file().a solution pack – the same payload plus an identity (
name+version, which is what makes a bundle installable by name, upgradable and uninstallable) and publishing metadata (label,publisher,dependencies,iconLarge,postInstallConfig, …). It installs throughinstall_from_file().
Everything under the single export_<uuid>/ root directory follows the same
rules in both: one directory per content category, a data.json manifest in
the categories that need installers, and payload JSON named after the record.
What this module checks is structural – that the manifest and the files agree,
that every declared installer resolves, that category keys map to directories
that exist. It deliberately does not try to decide whether a field is valid
for some target, because that depends on the target’s schema; for that, run the
export through dry_run(), which
lets the appliance itself analyse the bundle.
Example
>>> from pyfsr.exports import Export
>>> arc = Export.open("myPack-1.0.0.zip")
>>> arc.kind
<ExportKind.SOLUTION_PACK: 'solutionpack'>
>>> [f.code for f in arc.problems() if f.is_error]
[]
Attributes¶
Exceptions¶
The file could not be read as a FortiSOAR export bundle at all. |
|
|
Classes¶
Which of the two bundle flavours an export is. |
|
str(object='') -> str |
|
One problem found in an export. |
|
An entry in a category |
|
An opened FortiSOAR export bundle. |
Module Contents¶
- exception pyfsr.exports.ExportError[source]¶
Bases:
ExceptionThe file could not be read as a FortiSOAR export bundle at all.
- exception pyfsr.exports.ExportValidationError(findings: list[Finding])[source]¶
Bases:
ExceptionExport.validate()found error-severity problems.
- class pyfsr.exports.Severity[source]¶
-
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
- class pyfsr.exports.Finding[source]¶
One problem found in an export.
codeis stable and machine-matchable;messageis for humans.
- class pyfsr.exports.Installer[source]¶
An entry in a category
data.jsonthat carries or references a payload.install_mode == "tgz"means the tarball travels inside the export at<category>/<installer_path>;"rpm"means the target fetches it from a repository, so nothing is bundled and nothing can be checked offline.
- class pyfsr.exports.Export[source]¶
An opened FortiSOAR export bundle.
Use
open(). The zip stays open for the object’s lifetime; use it as a context manager, or callclose(), if you care about the handle.- path: pathlib.Path[source]¶
- classmethod open(path: str | pathlib.Path) Export[source]¶
Open
pathand parse itsinfo.json.Raises
ExportErrorif the file is not a zip, has noinfo.json, or has more than one export root.
- property kind: ExportKind[source]¶
Solution pack (has an identity) or plain configuration export.
- property contents: dict[str, Any][source]¶
The raw
contentsmap. Values are lists for most categories and dicts keyed by apiName formodules/viewTemplates/views.
- entries(category: str) list[Any][source]¶
The entries of one
contentscategory, list- or dict-shaped alike.
- data_manifest(category: str) list[dict[str, Any]][source]¶
The
<category>/data.jsonrows, or[]when there is no manifest.
- playbook_members() collections.abc.Iterator[str][source]¶
Every playbook payload file (skips the collection metadata sidecars).
- problems(*, target_version: str | None = None) list[Finding][source]¶
Every structural problem found, most severe first.
target_versionenables thefsrMinCompatibilitycheck against the appliance you intend to import into.
- validate(*, target_version: str | None = None, strict: bool = False) list[Finding][source]¶
Like
problems(), but raises on errors.Returns the non-fatal findings so a caller can log them. With
strict=Truewarnings are fatal too.- Raises:
ExportValidationError – if any error (or, when strict, warning) was found.
- external_connectors() set[str][source]¶
Connectors the content calls that the export does not account for.
Not a defect – shipped Fortinet packs rely on the target already having these – but it is the install prerequisite list, and nothing else computes it. Platform builtins and Jinja-templated (dynamically dispatched) connector names are excluded.