Been using Imperva Cloud WAF for a few years now. The UI is fine for day-to-day stuff, but when it comes to a proper audit or needing to version-control our security rule sets, it's a nightmare. You either click through a hundred pages or rely on their API which, frankly, isn't great for bulk operations.
I got tired of it and wrote a Python script that uses the Imperva API to pull *everything*βsecurity policies, rules, exceptions, the whole lotβand dumps it into structured JSON files. This is crucial for us because we manage configs as code, and we need to track who changed what and when. The script handles pagination and organizes the output by site and policy. You'll need your API ID and key, and you have to set the base URL for your region.
Here's the core of it. It uses the `mx` (management API) endpoints.
```python
import requests
import json
import os
API_ID = os.environ.get('IMPERVA_API_ID')
API_KEY = os.environ.get('IMPERVA_API_KEY')
BASE_URL = 'https://api.imperva.com'
OUTPUT_DIR = './imperva_export'
headers = {
'x-API-Id': API_ID,
'x-API-Key': API_KEY,
'Content-Type': 'application/json'
}
def get_paginated_data(endpoint):
all_data = []
offset = 0
limit = 50
while True:
params = {'offset': offset, 'limit': limit}
resp = requests.get(f"{BASE_URL}{endpoint}", headers=headers, params=params)
resp.raise_for_status()
data = resp.json()
if not data:
break
all_data.extend(data)
if len(data) < limit:
break
offset += limit
return all_data
def export_site_policies(site_id):
# Get policies for a specific site
policies = get_paginated_data(f'/mx/v1/sites/{site_id}/policies')
for policy in policies:
policy_id = policy['id']
# Get the full policy details, including rules
policy_details = requests.get(f"{BASE_URL}/mx/v1/sites/{site_id}/policies/{policy_id}", headers=headers).json()
# Get policy exceptions
exceptions = get_paginated_data(f'/mx/v1/sites/{site_id}/policies/{policy_id}/exceptions')
policy_details['exceptions'] = exceptions
# Write to file
site_dir = os.path.join(OUTPUT_DIR, site_id)
os.makedirs(site_dir, exist_ok=True)
filename = os.path.join(site_dir, f"policy_{policy_id}.json")
with open(filename, 'w') as f:
json.dump(policy_details, f, indent=2)
def main():
# Get all sites
sites = get_paginated_data('/mx/v1/sites')
for site in sites:
site_id = site['id']
print(f"Exporting policies for site: {site_id}")
export_site_policies(site_id)
if __name__ == '__main__':
main()
```
To run it, you'd do something like:
```bash
export IMPERVA_API_ID="your_id"
export IMPERVA_API_KEY="your_key"
python3 imperva_export.py
```
A few things to watch out for:
* The API rate limits are there, so the script isn't lightning fast if you have hundreds of sites.
* The JSON structure from the API isn't always consistent, so you might need to tweak the parsing for certain policy types.
* This is a *pull* tool. I'm working on a diff tool to compare these JSON exports and highlight changes, which is the next piece for our audit pipeline.
This has saved us a ton of time during compliance reviews. Instead of granting auditors UI access, we just give them the JSON snapshot for the period in question and a diff from the previous period. Much cleaner.
Automate everything. Twice.
Oh, this is super relevant to what I'm working on right now! I've been trying to get a full inventory of our rules for a compliance review, and the manual export was... not fun.
Quick question about the pagination function - does the Imperva API use an `offset` and `limit` pattern, or is it a `next` token in the response? I had to deal with both in other services and it always trips me up a bit.
Also, +1 for using environment variables for the keys. I made that mistake once and accidentally committed a script with a (now expired) key to our internal repo. Never again! 😅