HFortix - Python SDK for Fortinet products (FortiOS, FortiManager, FortiAnalyzer)
Project description
HFortix - Fortinet Python SDK
Python client library for Fortinet products including FortiOS, FortiManager, and FortiAnalyzer.
🎯 Current Status
⚠️ BETA STATUS: All implementations are functional but in beta. APIs work correctly but may have incomplete parameter coverage or undiscovered edge cases.
FortiOS 7.6.5 Coverage (December 19, 2025):
- CMDB API: 37 of 37 categories (100% coverage) - 500+ endpoints 🔷 Beta
- Monitor API: 32 of 32 categories (100% coverage) - 200+ endpoints 🔷 Beta
- Log API: 5 of 5 categories (100% coverage) - Log reading functionality 🔷 Beta
- Service API: 3 of 3 categories (100% coverage) - 21 methods 🔷 Beta
- Overall: 77 of 77 categories (100% coverage) - 750+ API methods 🎉
Test Coverage: 226 test files (145 CMDB, 81 Monitor) with 75%+ pass rate (~50% of generated endpoints tested)
Note: All implementations remain in beta until version 1.0.0 with comprehensive unit test coverage.
🔥 Recent Highlights (December 2025):
- 🎉 100% API COVERAGE: Complete implementation of ALL documented FortiOS 7.6.5 API categories!
- 🚀 MASSIVE EXPANSION: Generated 500+ new endpoints across 37 CMDB + 32 Monitor categories
- 🔄 API Refactoring: All endpoints refactored with RESTful methods (.list(), .get(), .create(), .update(), .delete())
- ⚡ Dual-Pattern Interface: Flexible syntax supporting both dictionary and keyword arguments
- 🏗️ Repository Organization: Clean structure with all dev tools
- ⚡ Unified Module Generator: Single tool handles all edge cases (digit-prefixed names, certificates, nested resources)
- ✨ Monitor API (v0.3.11): 6 categories with 50+ monitoring endpoints (firewall stats, sessions, EMS, etc.)
- ✨ Log Configuration (v0.3.11): 56 endpoints for comprehensive logging setup
- ✨ Firewall Expansion (v0.3.11): FTP proxy, ICAP, IPS, DoS policies, access-proxy (WAF)
📖 Documentation:
- User Guide: QUICKSTART.md - Getting started guide
- Async Guide: ASYNC_GUIDE.md - Async/await support documentation
- API Method Reference: ENDPOINT_METHODS.md - All 857 endpoints with available methods
- Helper Methods Guide: HELPER_METHODS.md - Safe existence checking and best practices
- API Coverage: API_COVERAGE.md - Implementation status by category
- Full Changelog: CHANGELOG.md - Complete version history
Latest Features (v0.3.16):
- ✨ Read-Only Mode: Block all write operations for safe testing and CI/CD
- Enable with
read_only=Trueparameter - Raises
ReadOnlyModeErroron POST/PUT/DELETE attempts - GET requests execute normally
- Perfect for testing, dry-run, training environments
- Enable with
- ✨ Operation Tracking: Complete audit logging of all API calls
- Enable with
track_operations=Trueparameter - Records timestamp, method, URL, data, status code, VDOM
- Access via
get_operations()andget_write_operations()methods - Useful for debugging, auditing, change logs, documentation
- Enable with
- ✨ Comprehensive Filter Documentation: Complete guide to FortiOS filtering
- New FILTERING_GUIDE.md with 8 operators
- 50+ practical examples for addresses, policies, interfaces, routes
- Advanced patterns: ranges, exclusions, combined filters, pagination
- ✨ Username/Password Authentication: Session-based authentication support
- Alternative to API token authentication
- Automatic session management with proactive re-authentication
- Configurable idle timeout (default: 5 minutes)
- Context manager support for auto-logout
- ⚠️ Works in FortiOS ≤7.4.x, removed in 7.6.x+ (use API tokens for new deployments)
- ✨ Firewall Policy Convenience Wrapper: Intuitive interface for policy management
- Access via
fgt.firewall.policywith explicit parameters - Simplified syntax instead of complex REST API calls
- Full CRUD +
.enable(),.disable(),.move(),.clone()
- Access via
Also in v0.3.16:
- ✨ Async/Await Support: Full dual-mode support for async operations
- Single
FortiOSclass works in both sync and async modes - All 750+ API methods support async with
mode="async"parameter - All helper methods (
.exists()) work transparently in both modes - Async context manager support with
async with - Zero breaking changes - existing sync code continues to work
- Single
- ✨ 288 Endpoints Updated: All
.exists()helper methods now async-aware - 🏗️ Refactored Architecture: Improved code quality and maintainability
- Protocol-based HTTP client interface (
IHTTPClient) for extensibility - Eliminated 744 lines of duplicated code (35% reduction)
- Shared base class (
BaseHTTPClient) for sync and async clients - Enhanced testability and consistency across sync/async modes
- Users can now provide custom HTTP client implementations
- Protocol-based HTTP client interface (
Also in v0.3.15:
- ✨ Request ID / Correlation Tracking: Auto-generated or custom request IDs for distributed tracing
- ✨ Circuit Breaker Pattern: Automatic fail-fast to prevent cascading failures (opens after 5 failures, auto-recovers)
- ✨ Connection Pool Metrics: Monitor HTTP client health with
get_connection_stats()method - ✨ Per-Endpoint Timeouts: Configure custom timeouts per endpoint with wildcard pattern support
- ✨ Structured Logging: Machine-readable logs with extra fields (request_id, endpoint, method, status_code, duration)
- ✨ 100% Backwards Compatible: All existing code works unchanged
Previous Release (v0.3.12):
- ✨ HTTP/2 Support: Modern httpx library with connection multiplexing for improved performance
- ✨ Automatic Retry Logic: Exponential backoff (1s, 2s, 4s, 8s, 30s max) for transient failures
- ✨ Enhanced Reliability: Retries on connection errors, timeouts, rate limits (429), server errors (500-504)
- ✨ Context Manager Support: Use
with HTTPClient(...) as client:for automatic cleanup - ✨ Retry Statistics: Track retry attempts by reason and endpoint
- ✨ Better Error Handling: Graceful fallback for non-JSON responses, improved logging
Previous Release (v0.3.11):
- ✨ FTP Proxy Category: FTP proxy configuration (1 endpoint)
- explicit: FTP proxy explicit configuration with SSL/TLS support
- FTPS support, SSL certificate management, custom encryption
- 10 parameters: status, ports, IPs, security actions, SSL settings
- Test coverage: 5 test sections with comprehensive validation
- ✨ Monitor API Categories: 6 categories implemented (18% coverage)
- firewall/: 39 endpoints for firewall monitoring
- Policy statistics, session monitoring, ACL counters
- Address objects, traffic shapers, GTP stats
- Special endpoints: policy-lookup (callable), clearpass-address (actions)
- endpoint-control/: 7 endpoints for FortiClient EMS monitoring
- azure/, casb/, extender-controller/, extension-controller/: Additional monitoring
- Test coverage: 39 firewall tests with 100% pass rate
- All endpoints support explicit parameters (no **kwargs)
- ✨ Log Configuration Category: 56 endpoints for comprehensive logging setup
- Nested object pattern:
fgt.api.cmdb.log.disk.filter.get() - Multiple FortiAnalyzer, syslog, TACACS+ server support
- Custom fields, event filters, threat weights
- Nested object pattern:
- ✨ ICAP Category: Complete ICAP integration (3 endpoints, 30+ parameters)
- ✨ IPS Category: Full IPS management (8 endpoints)
- Custom signatures, sensors, decoders, rules
- ✨ Monitoring & Report Categories: NPU-HPE monitoring, report layouts
- ✨ Firewall Category Expansion: 29 endpoints with nested objects
- DoS policies, access-proxy (reverse proxy/WAF)
- Schedule, service, shaper, SSH/SSL configurations
Previous Release (v0.3.10):
- ✨ Configurable Timeouts: Customize connection and read timeouts
connect_timeout: Connection establishment timeout (default: 10.0s)read_timeout: Response read timeout (default: 300.0s)- Example:
FortiOS(host='...', token='...', connect_timeout=30.0, read_timeout=600.0)
- ✨ URL Encoding for Special Characters: Automatic encoding of special characters in object names
- Handles
/,@,:, spaces, and other special characters - Works with objects like
Test_NET_192.0.2.0/24(IP addresses with CIDR notation) - Applied to all 145 CMDB endpoint files automatically
- Handles
- ✅ Bug Fix: Fixed 404 errors when object names contain special characters
Previous Release (v0.3.9):
- ✨ raw_json Parameter: All 200+ API methods now support
raw_json=Truefor full response access - ✨ Logging System: Global and per-instance logging control
- ✅ Code Quality: 100% PEP 8 compliance (black + isort + flake8)
- ✅ Comprehensive Tests: 200+ test files covering all endpoints
Previous Releases:
- v0.3.8: Dual-pattern interface for all create/update methods
- v0.3.7: Packaging and layout improvements
- v0.3.6: Hidden internal CRUD methods for cleaner autocomplete
- v0.3.5: Enhanced IDE autocomplete with PEP 561 type hints
- v0.3.4: Unified import syntax documentation
- v0.3.0: Firewall endpoints expansion
🎯 Features
- Unified Package: Import all Fortinet products from a single package
- Type-Safe & Type-Checked: Full PEP 561 compliance with mypy/pyright support for IDE autocomplete
- Async/Await Support: Full dual-mode operation - works with both sync and async code
- Modular Architecture: Each product module can be used independently
- PyPI Installation:
pip install hfortix- simple and straightforward - Comprehensive Exception Handling: 387+ FortiOS error codes with detailed descriptions
- Automatic Retry Logic: Built-in retry mechanism with exponential backoff for transient failures
- HTTP/2 Support: Modern HTTP client with connection multiplexing for improved performance
- Circuit Breaker: Prevents cascade failures with automatic recovery
- Simplified APIs: Auto-conversion for common patterns (e.g., address group members)
- Well-Documented: Extensive API documentation and examples
- Modern Python: Type hints, PEP 585 compliance, Python 3.10+
📦 Available Modules
| Module | Status | Description |
|---|---|---|
| FortiOS | ✅ Active | FortiGate firewall management API |
| FortiManager | ⏸️ Planned | Centralized management for FortiGate devices |
| FortiAnalyzer | ⏸️ Planned | Log analysis and reporting platform |
🚀 Installation
From PyPI (Recommended)
pip install hfortix
📖 Quick Start
Basic Usage
from hfortix import FortiOS
# Initialize with API token (recommended)
fgt = FortiOS(
host='192.168.1.99',
token='your-api-token',
verify=False # Use True in production with valid SSL cert
)
# List firewall addresses
addresses = fgt.api.cmdb.firewall.address.list()
print(f"Found {len(addresses['results'])} addresses")
# Create a new address
result = fgt.api.cmdb.firewall.address.create(
name='web-server',
subnet='192.168.10.50/32',
comment='Production web server'
)
Raw JSON Response ✨
All API methods support raw_json parameter for full response access:
# Default behavior - returns just the results
addresses = fgt.api.cmdb.firewall.address.list()
print(addresses) # ['obj1', 'obj2', 'obj3']
# With raw_json=True - returns complete API response
response = fgt.api.cmdb.firewall.address.list(raw_json=True)
print(response['http_status']) # 200
print(response['status']) # 'success'
print(response['results']) # ['obj1', 'obj2', 'obj3']
print(response['serial']) # 'FGT60FTK19000001'
print(response['version']) # 'v7.6.5'
# Useful for error checking
result = fgt.api.cmdb.firewall.address.get('web-server', raw_json=True)
if result['http_status'] == 200:
print(f"Object found: {result['results']}")
else:
print(f"Error: {result.get('error', 'Unknown error')}")
Available on: All 45+ API methods (100% coverage)
Logging Control ✨
Control logging output globally or per-instance:
import hfortix
from hfortix import FortiOS
# Enable detailed logging globally for all instances
hfortix.set_log_level('DEBUG') # Very verbose - all requests/responses
hfortix.set_log_level('INFO') # Normal - request summaries
hfortix.set_log_level('WARNING') # Quiet - only warnings (default)
hfortix.set_log_level('ERROR') # Silent - only errors
hfortix.set_log_level('OFF') # No logging output
# Or enable logging for a specific instance
fgt = FortiOS('192.168.1.99', token='your-token', debug='info')
# Automatic sensitive data sanitization
# Tokens, passwords, and API keys are automatically masked in logs
Features:
- 5 log levels (DEBUG, INFO, WARNING, ERROR, OFF)
- Automatic sensitive data sanitization
- Request/response logging with timing
- Hierarchical loggers for fine-grained control
Read-Only Mode & Operation Tracking ✨ NEW in v0.3.16
Safe testing and comprehensive audit logging:
from hfortix import FortiOS
from hfortix.FortiOS.exceptions_forti import ReadOnlyModeError
# 1. Read-Only Mode - Block all write operations
fgt = FortiOS('192.168.1.99', token='your-token', read_only=True)
# GET requests work normally
status = fgt.api.monitor.system.status.get() # ✅ Works
try:
# POST/PUT/DELETE requests are blocked
fgt.api.cmdb.firewall.address.post(data={"name": "test", "subnet": "10.0.0.1/32"})
except ReadOnlyModeError as e:
print(f"Blocked: {e}") # ❌ Raises ReadOnlyModeError
# Perfect for: testing, CI/CD pipelines, dry-run, training environments
# 2. Operation Tracking - Audit logging of all API calls
fgt = FortiOS('192.168.1.99', token='your-token', track_operations=True)
# Make some API calls
fgt.api.monitor.system.status.get()
fgt.api.cmdb.firewall.address.get(filter="name=@web")
# Get complete audit log
operations = fgt.get_operations()
for op in operations:
print(f"{op['timestamp']} {op['method']} {op['path']} - Status: {op['status_code']}")
# Get only write operations (POST/PUT/DELETE)
write_ops = fgt.get_write_operations()
for op in write_ops:
print(f"{op['method']} {op['path']}")
if op['data']:
print(f" Data: {op['data']}")
# 3. Combine both features
fgt = FortiOS('192.168.1.99', token='your-token',
read_only=True, track_operations=True)
# Test your automation script safely while logging everything
try:
# Your automation code here
fgt.api.cmdb.firewall.policy.post(data={...}) # Blocked
except ReadOnlyModeError:
pass
# Review what would have been executed
blocked_ops = [op for op in fgt.get_operations() if op.get('blocked_by_read_only')]
print(f"Would have executed {len(blocked_ops)} write operations")
Use Cases:
- Testing: Test automation scripts without affecting production
- CI/CD: Validate configuration changes in pipelines
- Auditing: Track all API operations for compliance
- Documentation: Auto-generate change logs from operations
- Debugging: See exact API call sequence
- Training: Safe environment for learning
Advanced Filtering ✨ Enhanced in v0.3.16
Complete guide to FortiOS native filter operators:
from hfortix import FortiOS
fgt = FortiOS('192.168.1.99', token='your-token')
# All 8 FortiOS filter operators:
addresses = fgt.api.cmdb.firewall.address.get(filter="name==web-server") # Equals
addresses = fgt.api.cmdb.firewall.address.get(filter="name!=test") # Not equals
addresses = fgt.api.cmdb.firewall.address.get(filter="subnet=@10.0") # Contains
addresses = fgt.api.cmdb.firewall.address.get(filter="subnet!@192.168") # Not contains
policies = fgt.api.cmdb.firewall.policy.get(filter="policyid<100") # Less than
policies = fgt.api.cmdb.firewall.policy.get(filter="policyid<=100") # Less than or equal
policies = fgt.api.cmdb.firewall.policy.get(filter="policyid>100") # Greater than
policies = fgt.api.cmdb.firewall.policy.get(filter="policyid>=100") # Greater than or equal
# Combine multiple filters (AND logic)
policies = fgt.api.cmdb.firewall.policy.get(
filter="status==enable&action==accept&policyid>=100&policyid<=200"
)
# Range queries
addresses = fgt.api.cmdb.firewall.address.get(
filter="subnet=@10.&comment=@production"
)
# See FILTERING_GUIDE.md for 50+ examples
Documentation: FILTERING_GUIDE.md
Username/Password Authentication ✨ NEW in v0.3.16
Session-based authentication with automatic session management:
from hfortix import FortiOS
# Context manager - recommended (auto-logout)
with FortiOS('192.168.1.99', username='admin', password='password',
verify=False) as fgt:
# Session automatically created
addresses = fgt.api.cmdb.firewall.address.get()
# Session automatically cleaned up on exit
# Manual session management
fgt = FortiOS('192.168.1.99', username='admin', password='password')
# Login happens automatically
addresses = fgt.api.cmdb.firewall.address.get()
fgt.close() # Manual logout
# Configure session timeout (default: 5 minutes)
with FortiOS('192.168.1.99', username='admin', password='password',
session_idle_timeout=600) as fgt: # 10 minutes
# Proactive re-auth at 80% of timeout (8 minutes)
# Timer resets on each request (idle timer)
addresses = fgt.api.cmdb.firewall.address.get()
# Disable proactive re-auth
fgt = FortiOS('192.168.1.99', username='admin', password='password',
session_idle_timeout=None)
Important Notes:
- ⚠️ Username/password works in FortiOS ≤7.4.x but removed in 7.6.x+
- 🔒 Use API token authentication for production deployments
- ⏱️ Idle timer resets on each API request
- 🔄 Proactive re-auth at 80% of idle timeout
- 📌 Context manager required for proactive re-auth
Advanced HTTP Features ✨ v0.3.15
Enterprise-grade reliability and observability features:
from hfortix import FortiOS
fgt = FortiOS('192.168.1.99', token='your-token', verify=False)
# 1. Request correlation tracking (auto-generated or custom)
result = fgt._client.request(
"GET", "monitor", "system/status",
request_id="batch-update-2025-12-17"
)
# 2. Monitor connection pool health
stats = fgt._client.get_connection_stats()
print(f"Circuit breaker: {stats['circuit_breaker_state']}")
print(f"HTTP/2 enabled: {stats['http2_enabled']}")
# 3. Circuit breaker pattern (automatic fail-fast)
# Opens after 5 consecutive failures, auto-recovers after 60s
try:
result = fgt.api.monitor.system.status.get()
except RuntimeError as e:
if "Circuit breaker is OPEN" in str(e):
print("Service is down - failing fast")
fgt._client.reset_circuit_breaker() # Manual reset
# 4. Per-endpoint timeouts (custom timeouts for slow endpoints)
fgt._client.configure_endpoint_timeout('monitor/*', read=10.0)
fgt._client.configure_endpoint_timeout('cmdb/firewall/policy', read=600.0)
# 5. Structured logging (machine-readable logs with extra fields)
# All logs include: request_id, endpoint, method, status_code, duration
# Compatible with Elasticsearch, Splunk, CloudWatch
Benefits:
- Request Tracking: Trace requests across distributed systems
- Circuit Breaker: Prevent cascading failures during outages
- Metrics: Monitor connection pool health and performance
- Fine-tuned Timeouts: Different timeouts for fast/slow endpoints
- Structured Logs: Machine-readable for log aggregation tools
Dual-Pattern Interface ✨
HFortix supports flexible dual-pattern syntax - use dictionaries, keywords, or mix both:
# Pattern 1: Dictionary-based (great for templates)
config = {
'name': 'web-server',
'subnet': '192.168.10.50/32',
'comment': 'Production web server'
}
fgt.api.cmdb.firewall.address.create(data_dict=config)
# Pattern 2: Keyword-based (great for readability)
fgt.api.cmdb.firewall.address.create(
name='web-server',
subnet='192.168.10.50/32',
comment='Production web server'
)
# Pattern 3: Mixed (template + overrides)
base_config = load_template('address_template.json')
fgt.api.cmdb.firewall.address.create(
data_dict=base_config,
name=f'server-{site_id}', # Override name
comment=f'Site: {site_name}'
)
Available on: 43 methods across 13 categories (100% coverage)
- All CMDB create/update operations (38 endpoints)
- Service operations (5 methods)
Exception Handling
from hfortix import (
FortiOS,
APIError,
ResourceNotFoundError,
DuplicateEntryError
)
try:
result = fgt.api.cmdb.firewall.address.create(
name='test-address',
subnet='10.0.0.0/24'
)
except DuplicateEntryError as e:
print(f"Address already exists: {e}")
except ResourceNotFoundError as e:
print(f"Resource not found: {e}")
except APIError as e:
print(f"API Error: {e.message}")
print(f"HTTP Status: {e.http_status}")
print(f"Error Code: {e.error_code}")
🏗️ Project Structure
fortinet/
├── hfortix/ # Main package
│ ├── __init__.py # Public API exports
│ ├── exceptions.py # Base exceptions
│ ├── exceptions_forti.py # FortiOS-specific error codes/helpers
│ ├── py.typed # PEP 561 marker
│ └── FortiOS/
│ ├── __init__.py
│ ├── fortios.py # FortiOS client
│ ├── http_client.py # Internal HTTP client
│ ├── exceptions.py # FortiOS re-exports
│ └── api/
│ └── v2/
│ ├── cmdb/ # Configuration endpoints
│ ├── log/ # Log reading endpoints
│ ├── service/ # Service operations
│ └── monitor/ # Monitoring endpoints
├── setup.py # Package configuration
├── pyproject.toml # Build system config
├── README.md # This file
├── QUICKSTART.md # Quick reference guide
├── API_COVERAGE.md # API implementation status
└── CHANGELOG.md # Version history
🔍 Module Discovery
Check which modules are available:
from hfortix import get_available_modules
modules = get_available_modules()
print(modules)
# {'FortiOS': True, 'FortiManager': False, 'FortiAnalyzer': False}
🎓 Examples
FortiOS - Firewall Address Management
from hfortix import FortiOS
fgt = FortiOS(host='192.168.1.99', token='your-token', verify=False)
# List addresses
addresses = fgt.api.cmdb.firewall.address.list()
# Create address
result = fgt.api.cmdb.firewall.address.create(
name='web-server',
subnet='10.0.1.100/32',
comment='Production web server'
)
# Update address
result = fgt.api.cmdb.firewall.address.update(
name='web-server',
comment='Updated comment'
)
# Delete address
result = fgt.api.cmdb.firewall.address.delete(name='web-server')
FortiOS - DoS Protection (NEW!)
# Create IPv4 DoS policy with simplified API
result = fgt.api.cmdb.firewall.dos_policy.create(
policyid=1,
name='protect-web-servers',
interface='port3', # Simple string format
srcaddr=['all'], # Simple list format
dstaddr=['web-servers'],
service=['HTTP', 'HTTPS'],
status='enable',
comments='Protect web farm from DoS attacks'
)
# API automatically converts to FortiGate format:
# interface='port3' → {'q_origin_key': 'port3'}
# service=['HTTP'] → [{'name': 'HTTP'}]
# Custom anomaly detection thresholds
result = fgt.api.cmdb.firewall.dos_policy.create(
policyid=2,
name='strict-dos-policy',
interface='wan1',
srcaddr=['all'],
dstaddr=['all'],
service=['ALL'],
anomaly=[
{'name': 'tcp_syn_flood', 'threshold': 500, 'action': 'block'},
{'name': 'udp_flood', 'threshold': 1000, 'action': 'block'}
]
)
FortiOS - Reverse Proxy/WAF (NEW!)
# Create access proxy (requires VIP with type='access-proxy')
result = fgt.api.cmdb.firewall.access_proxy.create(
name='web-proxy',
vip='web-vip', # VIP must be type='access-proxy'
auth_portal='enable',
log_blocked_traffic='enable',
http_supported_max_version='2.0',
svr_pool_multiplex='enable'
)
# Create virtual host with simplified API
result = fgt.api.cmdb.firewall.access_proxy_virtual_host.create(
name='api-vhost',
host='*.api.example.com',
host_type='wildcard',
ssl_certificate='Fortinet_Factory' # String auto-converts to list
)
# API automatically converts:
# ssl_certificate='cert' → [{'name': 'cert'}]
FortiOS - Address & Address Group Management (NEW!)
# Create IPv4 address (subnet)
result = fgt.api.cmdb.firewall.address.create(
name='internal-net',
type='ipmask',
subnet='192.168.1.0/24',
comment='Internal network'
)
# Create IPv4 address (IP range)
result = fgt.api.cmdb.firewall.address.create(
name='dhcp-range',
type='iprange',
start_ip='192.168.1.100',
end_ip='192.168.1.200'
)
# Create IPv4 address (FQDN)
result = fgt.api.cmdb.firewall.address.create(
name='google-dns',
type='fqdn',
fqdn='dns.google.com'
)
# Create IPv6 address
result = fgt.api.cmdb.firewall.address6.create(
name='ipv6-internal',
type='ipprefix',
ip6='2001:db8::/32',
comment='IPv6 internal network'
)
# Create address group with simplified API
result = fgt.api.cmdb.firewall.addrgrp.create(
name='internal-networks',
member=['subnet1', 'subnet2', 'subnet3'], # Simple string list!
comment='All internal networks'
)
# API automatically converts:
# member=['addr1', 'addr2'] → [{'name': 'addr1'}, {'name': 'addr2'}]
# Create IPv6 address group
result = fgt.api.cmdb.firewall.addrgrp6.create(
name='ipv6-internal-networks',
member=['ipv6-subnet1', 'ipv6-subnet2'],
comment='All internal IPv6 networks'
)
# Create IPv6 address template
result = fgt.api.cmdb.firewall.address6_template.create(
name='ipv6-subnet-template',
ip6='2001:db8::/32',
subnet_segment_count=2,
comment='IPv6 subnet template'
)
FortiOS - Schedule Management
# Create recurring schedule
result = fgt.api.cmdb.firewall.schedule.recurring.create(
name='business-hours',
day=['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
start='08:00',
end='18:00'
)
# Create one-time schedule
from datetime import datetime, timedelta
tomorrow = datetime.now() + timedelta(days=1)
start = f"09:00 {tomorrow.strftime('%Y/%m/%d')}"
end = f"17:00 {tomorrow.strftime('%Y/%m/%d')}"
result = fgt.api.cmdb.firewall.schedule.onetime.create(
name='maintenance-window',
start=start,
end=end,
color=5
)
FortiOS - Routing Protocols (Singleton Endpoints) ⚠️
Important: Routing protocol configurations use a different pattern than collection endpoints.
Collection Endpoints (addresses, policies, etc.) support standard CRUD:
# Standard CRUD - simple and intuitive
fgt.api.cmdb.firewall.address.create(name='test', subnet='192.168.1.0/24')
fgt.api.cmdb.firewall.address.update(name='test', comment='updated')
fgt.api.cmdb.firewall.address.delete('test')
Singleton Endpoints (BGP, OSPF, RIP, ISIS, etc.) require GET→Modify→PUT pattern:
# BGP Neighbor Management - requires full config update
# Step 1: Get current BGP configuration
result = fgt.api.cmdb.router.bgp.get()
# Step 2: Extract config (handles different response formats)
if isinstance(result, list):
config = result[0] if result else {}
elif isinstance(result, dict) and 'results' in result:
config = result['results']
if isinstance(config, list):
config = config[0] if config else {}
else:
config = result
# Step 3: Modify nested objects (neighbors, networks, etc.)
neighbors = config.get('neighbor', [])
neighbors.append({
'ip': '10.0.0.1',
'remote-as': 65001,
'description': 'New BGP neighbor',
'shutdown': 'enable' # Disabled for safety
})
config['neighbor'] = neighbors
# Step 4: Send entire config back
result = fgt.api.cmdb.router.bgp.update(data_dict=config)
# Verify
config = fgt.api.cmdb.router.bgp.get()
# Extract config again (same as step 2)
neighbors = config.get('neighbor', []) if isinstance(config, dict) else []
print(f"BGP now has {len(neighbors)} neighbors")
# OSPF Network Management - same pattern
config = fgt.api.cmdb.router.ospf.get()
# Extract config (same pattern as BGP)
if isinstance(config, list):
config = config[0] if config else {}
networks = config.get('network', [])
networks.append({
'id': 9999,
'prefix': '192.168.1.0 255.255.255.0'
})
config['network'] = networks
fgt.api.cmdb.router.ospf.update(data_dict=config)
# RIP Network Management
config = fgt.api.cmdb.router.rip.get()
if isinstance(config, list):
config = config[0]
networks = config.get('network', [])
networks.append({'id': 1, 'prefix': '10.0.0.0 255.0.0.0'})
config['network'] = networks
fgt.api.cmdb.router.rip.update(data_dict=config)
Why This Pattern?
- FortiOS API design: Routing protocols are singleton objects (only one BGP/OSPF/RIP config per VDOM)
- Nested objects (neighbors, networks, areas) are managed as lists within the main config
- The API requires sending the entire configuration on updates to maintain consistency
Future Enhancement: Helper methods are planned to simplify this pattern:
# Planned for future release (not yet available)
fgt.api.cmdb.router.bgp.add_neighbor(ip='10.0.0.1', remote_as=65001)
fgt.api.cmdb.router.bgp.remove_neighbor('10.0.0.1')
fgt.api.cmdb.router.bgp.list_neighbors()
Affected Endpoints:
router/bgp- BGP neighbors, networks, aggregate addresses, VRFsrouter/ospf- OSPF areas, interfaces, networks, neighborsrouter/ospf6- OSPFv3 areas, interfacesrouter/rip- RIP networks, neighbors, interfacesrouter/ripng- RIPng networks, neighborsrouter/isis- IS-IS NETs, interfacesrouter/bfd- BFD neighbors (IPv4)router/bfd6- BFD neighbors (IPv6)
See the test files in the development workspace for complete working examples.
### Helper Methods - Safe Existence Checking ✨
The `.exists()` helper method provides safe existence checking on 288 CMDB endpoints without raising exceptions:
```python
from hfortix import FortiOS
fgt = FortiOS(host='192.168.1.99', token='your-token', verify=False)
# Check if object exists before operations
if fgt.api.cmdb.firewall.address.exists('web-server'):
print("Address already exists")
fgt.api.cmdb.firewall.address.update('web-server', comment='Updated')
else:
print("Creating new address")
fgt.api.cmdb.firewall.address.create(
name='web-server',
subnet='10.0.1.100/32'
)
# Safe deletion pattern
if fgt.api.cmdb.user.local.exists('testuser'):
fgt.api.cmdb.user.local.delete('testuser')
# Conditional processing
users = ['alice', 'bob', 'charlie']
for user in users:
if not fgt.api.cmdb.user.local.exists(user):
fgt.api.cmdb.user.local.create(
name=user,
type='password',
passwd='SecureP@ss123'
)
Available on: 288 endpoints with full CRUD operations (firewall addresses, policies, users, VPN configs, etc.)
📚 Complete Documentation:
- See HELPER_METHODS.md for detailed guide with examples
- See ENDPOINT_METHODS.md for complete API method reference
Exception Hierarchy
Exception
└── FortinetError (base)
├── AuthenticationError
├── AuthorizationError
└── APIError
├── ResourceNotFoundError (404)
├── BadRequestError (400)
├── MethodNotAllowedError (405)
├── RateLimitError (429)
├── ServerError (500)
├── DuplicateEntryError (-5, -15, -100)
├── EntryInUseError (-23, -94, -95)
├── InvalidValueError (-651, -1, -50)
└── PermissionDeniedError (-14, -37)
🧪 Testing
Note: This SDK is currently in beta (v0.3.x). All endpoints are functional but will remain in beta status until version 1.0.0 with comprehensive unit test coverage.
Current Status:
- All implemented endpoints are tested against live FortiGate devices
- Integration testing performed during development
- Unit test framework planned for v1.0.0 release
📝 Version
Current version: 0.3.16 (See CHANGELOG.md for release notes)
from hfortix import get_version
print(get_version())
🤝 Contributing
Contributions are welcome! Please feel free to:
- Report bugs and issues
- Suggest new features or improvements
- Submit pull requests
For code contributions:
- Fork the repository
- Create a feature branch
- Make your changes with proper tests
- Submit a pull request with clear description
📄 License
Proprietary License - Free for personal, educational, and business use.
You may:
- Use for personal projects and learning
- Use in your business operations
- Deploy in client environments
- Use in managed services and technical support
You may not:
- Sell the software itself as a standalone product
- Redistribute as your own product
See CHANGELOG.md v0.2.0 for details.
🔗 Links
💡 Tips
- Use API Tokens: Only token-based authentication is supported for FortiOS REST API
- Error Handling: Always catch specific exceptions for better error handling
- Verify SSL: Set
verify=Truein production (requires valid certificates) - Automatic Retries: Built-in retry logic handles transient failures (429, 500, 502, 503, 504)
- Connection Pooling: HTTP/2 support with connection multiplexing for better performance
- Timeout Configuration: Customize
connect_timeoutandread_timeoutfor your environment - Logging: Use
hfortix.set_log_level('INFO')for request/response debugging
⚙️ Configuration
Environment Variables
export FGT_HOST="192.168.1.99"
export FGT_TOKEN="your-api-token"
export FGT_VERIFY_SSL="false"
Using .env File
from dotenv import load_dotenv
import os
load_dotenv()
fgt = FortiOS(
host=os.getenv('FGT_HOST'),
token=os.getenv('FGT_TOKEN'),
verify=os.getenv('FGT_VERIFY_SSL', 'false').lower() == 'true'
)
🎯 Roadmap
- [🚧] FortiOS API implementation (In Development)
- Exception handling system (387 error codes)
- Base client architecture with HTTP/2, retry logic, circuit breaker
- [🔷] CMDB endpoints (Beta - 57.5% coverage, 23/40 categories)
- [🔷] Firewall (address, policy, service, DoS, ICAP, IPS, etc.) - Beta
- [🔷] System (interface, admin, global, etc.) - Beta
- [🔷] Router (static, bgp, ospf, rip, isis, etc.) - NEW Beta ⚠️ See note below
- [🔷] VPN (IPsec, SSL, etc.) - Beta
- [🔷] Log (disk, syslog, fortianalyzer, etc.) - Beta
- [🔷] Wireless Controller, User, Web Filter, Application - Beta
- Remaining 17 categories (Switch Controller, WAD, etc.)
- [🔷] Monitor endpoints (Beta - 18% coverage, 6/33 categories)
- [🔷] Firewall, Endpoint Control, Azure, CASB, Extender - Beta
- Remaining 27 categories
- [🔷] Service endpoints (Beta - 100% coverage, 3/3 categories)
- Sniffer, Security Rating, etc.
- [🔷] Log endpoints (Beta - 100% coverage, 5/5 categories)
- Traffic, Event, Virus, etc.
- Modular package architecture
- PyPI package publication (hfortix on PyPI)
- FortiManager module (Not Started)
- FortiAnalyzer module (Not Started)
- Helper methods for singleton routing endpoints (Planned)
- Async/await support (Implemented in v0.3.15)
- CLI tool (Planned)
⚠️ Important Note: Singleton Routing Endpoints (Beta)
Routing protocol configurations (BGP, OSPF, RIP, ISIS, etc.) use a different pattern than collection endpoints:
-
Collection Endpoints (addresses, policies, etc.): Use standard CRUD operations
# Simple add/remove pattern fgt.api.cmdb.firewall.address.create(name='test', subnet='192.168.1.0/24') fgt.api.cmdb.firewall.address.delete('test')
-
Singleton Endpoints (bgp, ospf, rip, isis, etc.): Require GET→Modify→PUT pattern
# Must get entire config, modify, and send back config = fgt.api.cmdb.router.bgp.get() config['neighbor'].append({'ip': '10.0.0.1', 'remote-as': 65001}) fgt.api.cmdb.router.bgp.update(data_dict=config)
Why? This is a FortiOS API design - routing protocols are singleton objects with nested lists (neighbors, networks, areas). The API requires sending the entire configuration on updates.
Future Enhancement: Helper methods like add_neighbor(), remove_neighbor(), list_neighbors() are planned to simplify this pattern.
Affected Endpoints:
router/bgp- BGP neighbors, networks, VRFsrouter/ospf- OSPF areas, interfaces, networksrouter/ospf6- OSPFv3 configurationrouter/rip- RIP networks, neighborsrouter/ripng- RIPng configurationrouter/isis- IS-IS NETs, interfacesrouter/bfd- BFD neighbors (IPv4)router/bfd6- BFD neighbors (IPv6)
All implementations remain in BETA until version 1.0.0 with comprehensive unit test coverage.
👤 Author
Herman W. Jacobsen
- Email: herman@wjacobsen.fo
- LinkedIn: linkedin.com/in/hermanwjacobsen
- GitHub: @hermanwjacobsen
Built with ❤️ for the Fortinet community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hfortix-0.3.16.tar.gz.
File metadata
- Download URL: hfortix-0.3.16.tar.gz
- Upload date:
- Size: 796.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d60152aae45ef144c393f2918580427103be37273e1433154a2adad7212e833
|
|
| MD5 |
4914e11ace7ca300b163b26e23d59f4e
|
|
| BLAKE2b-256 |
983918e155430daa8c545b819f3b5749b0bac8abf104bfabf13a739835e881bd
|
File details
Details for the file hfortix-0.3.16-py3-none-any.whl.
File metadata
- Download URL: hfortix-0.3.16-py3-none-any.whl
- Upload date:
- Size: 2.2 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50e8c4c5166e65874defde309e74f82596699082abd917c9dc57b360ebd64b07
|
|
| MD5 |
1aaf5cc35b10ac35bf48e7b93246f1f1
|
|
| BLAKE2b-256 |
a447d138f68dcfb79daeb44e3c679713df227043fa2c7256fd40d02cf79cb96b
|