From 15b161fe857add3bb5920361de10f5b4d83511b3 Mon Sep 17 00:00:00 2001 From: AntoineCbw Date: Fri, 30 May 2025 13:02:22 +0000 Subject: [PATCH] Add assets synchronisation between two instance's script --- examples/two_instance_sync/README.md | 63 +++++++++++++++++++++++ examples/two_instance_sync/sync_assets.py | 39 ++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 examples/two_instance_sync/README.md create mode 100644 examples/two_instance_sync/sync_assets.py diff --git a/examples/two_instance_sync/README.md b/examples/two_instance_sync/README.md new file mode 100644 index 0000000..a4c05a7 --- /dev/null +++ b/examples/two_instance_sync/README.md @@ -0,0 +1,63 @@ +# Synchronizing Data Between Two Cyberwatch Instances + +This script lets you synchronize asset data from a **source Cyberwatch instance (Instance A)** to a **destination instance (Instance B)** using the Cyberwatch Python CLI. + +This process is useful for air-gapped networks, backup purposes, or centralized analysis of vulnerability data. + +--- + +## API Key Requirements + +- Instance A (source): API key with **read-only** permissions +- Instance B (destination): API key with **full access** permissions + +Make sure your Cyberwatch CLI or environment is configured with the appropriate API key for each step below. + +> If you get an `"api_url not found"` error, place `sync_assets.py` inside the `examples` directory and run it again. + +--- + +## Step 1 – Export Data from Instance A + +> Use the **read-only** API key from **Instance A** + +The Python script `sync_assets.py` fetches all assets from Instance A and saves their vulnerability data in `.txt` files. + +Each `.txt` file corresponds to a single asset and is saved in the `export` directory (created automatically if it doesn't exist). + +Run the script with: + +```bash +python3 sync_assets.py +``` + +Output files will be located in the `export/` folder relative to where the script is run. + +--- + +## Step 2 – Upload Data to Instance B + +> Use the **full-access** API key from **Instance B** + +1. Switch your API configuration to use the **Instance B full-access** API key +2. Go to the `export/` directory where the `.txt` files were saved +3. Upload all `.txt` files using: + +```bash +cyberwatch-cli airgap upload export/*.txt +``` +or +```bash +find ./export -name "*.txt" -exec sudo cyberwatch-cli airgap upload {} \; +``` + +> On Windows, the CLI automatically uploads files from the `uploads` folder by default. +> To use the `export` directory, provide the full path to your `.txt` files. + +--- + +## Result + +- All assets from Instance A are successfully transferred to Instance B +- Instance B automatically analyzes and recalculates vulnerability information upon upload + diff --git a/examples/two_instance_sync/sync_assets.py b/examples/two_instance_sync/sync_assets.py new file mode 100644 index 0000000..a42632b --- /dev/null +++ b/examples/two_instance_sync/sync_assets.py @@ -0,0 +1,39 @@ +import os +from cyberwatch_api import Cyberwatch_Pyhelper +from urllib3.exceptions import InsecureRequestWarning +import warnings + +warnings.simplefilter('ignore', InsecureRequestWarning) +OUTPUT_DIR = "export" + +def retrieve_assets(): + """Retrieve all assets for a cyberwatch node.""" + assets = {} + apiResponse = Cyberwatch_Pyhelper().request( + method="GET", + endpoint="/api/v3/vulnerabilities/servers", + verify_ssl=False + ) + print("Retrieving assets : 0") + for page in apiResponse: + for asset in page.json(): + assets[asset['hostname']] = asset['id'] + print("\033[A\033[A\nRetrieving assets : " + str(len(assets))) + return assets + +if OUTPUT_DIR: + os.makedirs(OUTPUT_DIR, exist_ok=True) + +ALL_ASSETS = retrieve_assets() + +for hostname in ALL_ASSETS: + output = Cyberwatch_Pyhelper().request( + method="GET", + endpoint=f"/api/v3/vulnerabilities/servers/{ALL_ASSETS[hostname]}/info", + verify_ssl=False + ) + safe_filename = f"{hostname}.txt".replace('/', '-') + filepath = os.path.join(OUTPUT_DIR or ".", safe_filename) + + with open(filepath, 'wb') as f: + f.write((next(output).text).encode())