Exporting and processing scan results in JSON

The result of SSLyze scans can be serialized to JSON for further processing. SSLyze also provides a helper class to parse JSON scan results; it can be used to process the results of SSLyze scans in a separate Python program.

A schema of the JSON output is available in the code repository at ./json_output_schema.json.

Exporting results to JSON when using the CLI

When using the CLI, the scan results can be exported to a JSON file using the --json_out option:

$ python -m sslyze www.google.com www.facebook.com --json_out=result.json

The generated JSON file can then be parsed, as described in the “Parsing the JSON output” section.

Exporting results to JSON when using the API

When using the API, the scan results can be exported to a JSON file using the SslyzeOutputAsJson.from_orm() method:

def example_json_result_output(
    json_file_out: Path,
    all_server_scan_results: List[ServerScanResult],
    date_scans_started: datetime,
    date_scans_completed: datetime,
) -> None:
    json_output = SslyzeOutputAsJson(
        server_scan_results=[ServerScanResultAsJson.model_validate(result) for result in all_server_scan_results],
        invalid_server_strings=[],  # Not needed here - specific to the CLI interface
        date_scans_started=date_scans_started,
        date_scans_completed=date_scans_completed,
    )
    json_output_as_str = json_output.model_dump_json()
    json_file_out.write_text(json_output_as_str)

Parsing the JSON output

A JSON results file generated by SSLyze can then be parsed using the SslyzeOutputAsJson.from_file() method:

def example_json_result_parsing(results_as_json_file: Path) -> None:
    # SSLyze scan results serialized to JSON were saved to this file using --json_out
    results_as_json = results_as_json_file.read_text()

    # These results can be parsed
    parsed_results = SslyzeOutputAsJson.model_validate_json(results_as_json)

    # Making it easy to do post-processing and inspection of the results
    print("The following servers were scanned:")
    for server_scan_result in parsed_results.server_scan_results:
        print(f"\n****{server_scan_result.server_location.hostname}:{server_scan_result.server_location.port}****")

        if server_scan_result.scan_status == ServerScanStatusEnum.ERROR_NO_CONNECTIVITY:
            print(f"That scan failed with the following error:\n{server_scan_result.connectivity_error_trace}")
            continue

        assert server_scan_result.scan_result
        certinfo_attempt = server_scan_result.scan_result.certificate_info
        if certinfo_attempt.status == ScanCommandAttemptStatusEnum.ERROR:
            _print_failed_scan_command_attempt(certinfo_attempt)  # type: ignore
        else:
            certinfo_result = server_scan_result.scan_result.certificate_info.result
            assert certinfo_result
            for cert_deployment in certinfo_result.certificate_deployments:
                print(f"    SHA1 of leaf certificate: {cert_deployment.received_certificate_chain[0].fingerprint_sha1}")
            print("")

The resulting Python object then contains the scan results. Type annotations are available for all fields, thereby making it easier to process the results.