diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 99cd82f..3927116 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,3 +1,8 @@ +## Version 0.3.4 + +- Added support for External Dynamic Lists +- Added support for Auto Tag Actions (not yet supported by API) + ## Version 0.3.3 - Added support for URL Categories diff --git a/docs/sdk/config/objects/external_dynamic_lists.md b/docs/sdk/config/objects/external_dynamic_lists.md new file mode 100644 index 0000000..71266ef --- /dev/null +++ b/docs/sdk/config/objects/external_dynamic_lists.md @@ -0,0 +1,374 @@ +# External Dynamic Lists Configuration Object + +## Table of Contents + +1. [Overview](#overview) +2. [Core Methods](#core-methods) +3. [EDL Model Attributes](#edl-model-attributes) +4. [Exceptions](#exceptions) +5. [Basic Configuration](#basic-configuration) +6. [Usage Examples](#usage-examples) + - [Creating EDLs](#creating-edls) + - [Retrieving EDLs](#retrieving-edls) + - [Updating EDLs](#updating-edls) + - [Listing EDLs](#listing-edls) + - [Deleting EDLs](#deleting-edls) +7. [Managing Configuration Changes](#managing-configuration-changes) + - [Performing Commits](#performing-commits) + - [Monitoring Jobs](#monitoring-jobs) +8. [Error Handling](#error-handling) +9. [Best Practices](#best-practices) +10. [Full Script Examples](#full-script-examples) +11. [Related Models](#related-models) + +## Overview + +The `ExternalDynamicLists` class provides functionality to manage External Dynamic Lists (EDLs) in Palo Alto Networks' Strata +Cloud Manager. This class inherits from `BaseObject` and provides methods for creating, retrieving, updating, and deleting +EDLs of various types including IP, Domain, URL, IMSI, and IMEI lists with configurable update intervals. + +## Core Methods + +| Method | Description | Parameters | Return Type | +|------------|----------------------------|-----------------------------------------------|----------------------------------------| +| `create()` | Creates a new EDL | `data: Dict[str, Any]` | `ExternalDynamicListsResponseModel` | +| `get()` | Retrieves an EDL by ID | `edl_id: str` | `ExternalDynamicListsResponseModel` | +| `update()` | Updates an existing EDL | `edl: ExternalDynamicListsUpdateModel` | `ExternalDynamicListsResponseModel` | +| `delete()` | Deletes an EDL | `edl_id: str` | `None` | +| `list()` | Lists EDLs with filtering | `folder: str`, `**filters` | `List[ExternalDynamicListsResponseModel]` | +| `fetch()` | Gets EDL by name | `name: str`, `folder: str` | `ExternalDynamicListsResponseModel` | + +## EDL Model Attributes + +| Attribute | Type | Required | Description | +|--------------------|--------------|--------------|---------------------------------------------| +| `name` | str | Yes | Name of EDL (max 63 chars) | +| `id` | UUID | Yes* | Unique identifier (*response only) | +| `type` | TypeUnion | Yes | EDL type configuration | +| `url` | str | Yes | Source URL for EDL content | +| `description` | str | No | Description (max 255 chars) | +| `exception_list` | List[str] | No | List of exceptions | +| `auth` | AuthModel | No | Authentication credentials | +| `recurring` | RecurringUnion| Yes | Update schedule configuration | +| `folder` | str | Yes** | Folder location (**one container required) | +| `snippet` | str | Yes** | Snippet location (**one container required) | +| `device` | str | Yes** | Device location (**one container required) | + +## Exceptions + +| Exception | HTTP Code | Description | +|------------------------------|-----------|--------------------------------| +| `InvalidObjectError` | 400 | Invalid EDL data or format | +| `MissingQueryParameterError` | 400 | Missing required parameters | +| `NameNotUniqueError` | 409 | EDL name already exists | +| `ObjectNotPresentError` | 404 | EDL not found | +| `ReferenceNotZeroError` | 409 | EDL still referenced | +| `AuthenticationError` | 401 | Authentication failed | +| `ServerError` | 500 | Internal server error | + +## Basic Configuration + +
+ + +```python +from scm.client import Scm +from scm.config.objects import ExternalDynamicLists + +# Initialize client +client = Scm( + client_id="your_client_id", + client_secret="your_client_secret", + tsg_id="your_tsg_id" +) + +# Initialize EDL object +edls = ExternalDynamicLists(client) +``` + +
+ +## Usage Examples + +### Creating EDLs + +
+ + +```python +# IP-based EDL with daily updates +ip_edl_config = { + "name": "malicious-ips", + "folder": "Texas", + "type": { + "ip": { + "url": "https://threatfeeds.example.com/ips.txt", + "description": "Known malicious IPs", + "recurring": { + "daily": { + "at": "03" + } + }, + "auth": { + "username": "user123", + "password": "pass123" + } + } + } +} + +# Create IP EDL +ip_edl = edls.create(ip_edl_config) + +# Domain-based EDL with hourly updates +domain_edl_config = { + "name": "blocked-domains", + "folder": "Texas", + "type": { + "domain": { + "url": "https://threatfeeds.example.com/domains.txt", + "description": "Blocked domains list", + "recurring": { + "hourly": {} + }, + "expand_domain": True + } + } +} + +# Create domain EDL +domain_edl = edls.create(domain_edl_config) +``` + +
+ +### Retrieving EDLs + +
+ + +```python +# Fetch by name and folder +edl = edls.fetch(name="malicious-ips", folder="Texas") +print(f"Found EDL: {edl.name}") + +# Get by ID +edl_by_id = edls.get(edl.id) +print(f"Retrieved EDL: {edl_by_id.name}") +``` + +
+ +### Updating EDLs + +
+ + +```python +# Fetch existing EDL +existing_edl = edls.fetch(name="malicious-ips", folder="Texas") + +# Update attributes +existing_edl.description = "Updated malicious IP list" +existing_edl.type.ip.recurring = { + "five_minute": {} +} + +# Perform update +updated_edl = edls.update(existing_edl) +``` + +
+ +### Listing EDLs + +
+ + +```python +# List with direct filter parameters +filtered_edls = edls.list( + folder='Texas', + types=['ip', 'domain'] +) + +# Process results +for edl in filtered_edls: + print(f"Name: {edl.name}") + if hasattr(edl.type, 'ip'): + print(f"Type: IP, URL: {edl.type.ip.url}") + elif hasattr(edl.type, 'domain'): + print(f"Type: Domain, URL: {edl.type.domain.url}") + +# Define filter parameters as dictionary +list_params = { + "folder": "Texas", + "types": ["url"] +} + +# List with filters as kwargs +filtered_edls = edls.list(**list_params) +``` + +
+ +### Deleting EDLs + +
+ + +```python +# Delete by ID +edl_id = "123e4567-e89b-12d3-a456-426655440000" +edls.delete(edl_id) +``` + +
+ +## Managing Configuration Changes + +### Performing Commits + +
+ + +```python +# Prepare commit parameters +commit_params = { + "folders": ["Texas"], + "description": "Updated EDL configurations", + "sync": True, + "timeout": 300 # 5 minute timeout +} + +# Commit the changes +result = edls.commit(**commit_params) + +print(f"Commit job ID: {result.job_id}") +``` + +
+ +### Monitoring Jobs + +
+ + +```python +# Get status of specific job +job_status = edls.get_job_status(result.job_id) +print(f"Job status: {job_status.data[0].status_str}") + +# List recent jobs +recent_jobs = edls.list_jobs(limit=10) +for job in recent_jobs.data: + print(f"Job {job.id}: {job.type_str} - {job.status_str}") +``` + +
+ +## Error Handling + +
+ + +```python +from scm.exceptions import ( + InvalidObjectError, + MissingQueryParameterError, + NameNotUniqueError, + ObjectNotPresentError, + ReferenceNotZeroError +) + +try: + # Create EDL configuration + edl_config = { + "name": "test-edl", + "folder": "Texas", + "type": { + "ip": { + "url": "https://example.com/ips.txt", + "description": "Test IP list", + "recurring": { + "daily": { + "at": "03" + } + } + } + } + } + + # Create the EDL + new_edl = edls.create(edl_config) + + # Commit changes + result = edls.commit( + folders=["Texas"], + description="Added test EDL", + sync=True + ) + + # Check job status + status = edls.get_job_status(result.job_id) + +except InvalidObjectError as e: + print(f"Invalid EDL data: {e.message}") +except NameNotUniqueError as e: + print(f"EDL name already exists: {e.message}") +except ObjectNotPresentError as e: + print(f"EDL not found: {e.message}") +except ReferenceNotZeroError as e: + print(f"EDL still in use: {e.message}") +except MissingQueryParameterError as e: + print(f"Missing parameter: {e.message}") +``` + +
+ +## Best Practices + +1. **EDL Configuration** + - Use descriptive names + - Set appropriate update intervals + - Configure authentication when needed + - Validate source URLs + - Monitor update status + +2. **Container Management** + - Always specify exactly one container + - Use consistent container names + - Validate container existence + - Group related EDLs + +3. **Update Scheduling** + - Choose appropriate intervals + - Consider source update frequency + - Stagger updates for multiple EDLs + - Monitor update success + - Handle failures gracefully + +4. **Performance** + - Use appropriate pagination + - Cache frequently accessed EDLs + - Monitor EDL sizes + - Consider update impact + - Implement retry logic + +5. **Security** + - Validate source URLs + - Use HTTPS where possible + - Secure credentials + - Monitor for malicious content + - Regular audits + +## Full Script Examples + +Refer to +the [external_dynamic_lists.py example](https://github.com/cdot65/pan-scm-sdk/blob/main/examples/scm/config/objects/external_dynamic_lists.py). + +## Related Models + +- [ExternalDynamicListsCreateModel](../../models/objects/external_dynamic_lists_models.md#Overview) +- [ExternalDynamicListsUpdateModel](../../models/objects/external_dynamic_lists_models.md#Overview) +- [ExternalDynamicListsResponseModel](../../models/objects/external_dynamic_lists_models.md#Overview) diff --git a/docs/sdk/config/objects/index.md b/docs/sdk/config/objects/index.md index 2edb704..a7ed553 100644 --- a/docs/sdk/config/objects/index.md +++ b/docs/sdk/config/objects/index.md @@ -36,6 +36,10 @@ Manage application filters definitions, including their characteristics and asso Manage application group definitions, including their characteristics and associated members. +### [External Dynamic Lists](external_dynamic_lists.md) + +Manage EDLs. + ### [Service](service.md) Manage service definitions, including their characteristics and associated protocols / ports. diff --git a/docs/sdk/index.md b/docs/sdk/index.md index c155ee5..915f355 100644 --- a/docs/sdk/index.md +++ b/docs/sdk/index.md @@ -15,6 +15,7 @@ configuration objects and data models used to interact with Palo Alto Networks S - [Application](config/objects/application.md) - [Application Filters](config/objects/application_filters.md) - [Application Group](config/objects/application_group.md) + - [External Dynamic Lists](config/objects/external_dynamic_lists.md) - [Service](config/objects/service.md) - [Service Group](config/objects/service_group.md) - [Tag](config/objects/tag.md) @@ -33,6 +34,7 @@ configuration objects and data models used to interact with Palo Alto Networks S - [Application Models](models/objects/application_models.md) - [Application Filters Models](models/objects/application_filters_models.md) - [Application Group Models](models/objects/application_group_models.md) + - [External Dynamic Lists Models](models/objects/external_dynamic_lists_models.md) - [Service Models](models/objects/service_models.md) - [Service Group Models](models/objects/service_group_models.md) - [Tag Models](models/objects/tag_models.md) diff --git a/docs/sdk/models/objects/external_dynamic_lists_models.md b/docs/sdk/models/objects/external_dynamic_lists_models.md new file mode 100644 index 0000000..81a8f9c --- /dev/null +++ b/docs/sdk/models/objects/external_dynamic_lists_models.md @@ -0,0 +1,235 @@ +# External Dynamic Lists Models + +## Overview + +The External Dynamic Lists models provide a structured way to manage external dynamic lists in Palo Alto Networks' Strata +Cloud Manager. These models support various types of dynamic lists including IP, domain, URL, IMSI, and IMEI lists, with +configurable update intervals and authentication options. + +## Attributes + +| Attribute | Type | Required | Default | Description | +|---------------------|---------------|----------|------------|-----------------------------------------------------------------------| +| name | str | Yes | None | Name of the list. Max length: 63 chars. Must match pattern: ^[ a-zA-Z\d.\-_]+$ | +| type | TypeUnion | Yes* | None | Type of dynamic list (predefined_ip, predefined_url, ip, domain, url, imsi, imei) | +| folder | str | No** | None | Folder where list is defined. Max length: 64 chars | +| snippet | str | No** | None | Snippet where list is defined. Max length: 64 chars | +| device | str | No** | None | Device where list is defined. Max length: 64 chars | +| id | UUID | Yes*** | None | UUID of the list (response only) | +| description | str | No | None | Description of the list. Max length: 255 chars | +| url | str | Yes | "http://" | URL for fetching list content | +| exception_list | List[str] | No | None | List of exceptions | +| certificate_profile | str | No | None | Client certificate profile name | +| auth | AuthModel | No | None | Username/password authentication | +| recurring | RecurringUnion | Yes | None | Update interval configuration | +| expand_domain | bool | No | False | Enable domain expansion (domain type only) | + +\* Required for non-predefined lists +\** Exactly one container type (folder/snippet/device) must be provided for create operations +\*** Required for response model when snippet is not "predefined" + +## Exceptions + +The External Dynamic Lists models can raise the following exceptions during validation: + +- **ValueError**: Raised in several scenarios: + - When no container type or multiple container types are specified for create operations + - When ID is missing for non-predefined response models + - When type is missing for non-predefined response models + - When invalid recurring interval configuration is provided + - When invalid URL format is provided + - When name pattern validation fails + +## Model Validators + +### Container Type Validation + +For create operations, exactly one container type must be specified: + +
+ + +```python +from scm.models.objects import ExternalDynamicListsCreateModel + +# This will raise a validation error +try: + edl = ExternalDynamicListsCreateModel( + name="blocked-ips", + folder="Shared", + device="fw01", # Can't specify both folder and device + type={"ip": { + "url": "http://example.com/blocked.txt", + "recurring": {"hourly": {}} + }} + ) +except ValueError as e: + print(e) # "Exactly one of 'folder', 'snippet', or 'device' must be provided." +``` + +
+ +### Recurring Interval Validation + +The models support various recurring update intervals: + +
+ + +```python +# Five minute interval +edl = ExternalDynamicListsCreateModel( + name="blocked-ips", + folder="Shared", + type={"ip": { + "url": "http://example.com/blocked.txt", + "recurring": {"five_minute": {}} + }} +) + +# Daily at specific hour +edl = ExternalDynamicListsCreateModel( + name="blocked-ips", + folder="Shared", + type={"ip": { + "url": "http://example.com/blocked.txt", + "recurring": {"daily": {"at": "23"}} + }} +) + +# Weekly on specific day and time +edl = ExternalDynamicListsCreateModel( + name="blocked-ips", + folder="Shared", + type={"ip": { + "url": "http://example.com/blocked.txt", + "recurring": {"weekly": {"day_of_week": "monday", "at": "12"}} + }} +) +``` + +
+ +## Usage Examples + +### Creating an IP List + +
+ + +```python +from scm.config.objects import ExternalDynamicLists + +# Using dictionary +ip_list = { + "name": "blocked-ips", + "folder": "Shared", + "type": { + "ip": { + "description": "Blocked IP addresses", + "url": "http://example.com/blocked.txt", + "auth": { + "username": "user1", + "password": "pass123" + }, + "recurring": {"hourly": {}} + } + } +} + +edl = ExternalDynamicLists(api_client) +response = edl.create(ip_list) +``` + +
+ +### Creating a Domain List + +
+ + +```python +# Using model directly +from scm.models.objects import ( + ExternalDynamicListsCreateModel, + DomainType, + DomainModel, + AuthModel, + HourlyRecurringModel +) + +domain_list = ExternalDynamicListsCreateModel( + name="blocked-domains", + folder="Shared", + type=DomainType( + domain=DomainModel( + description="Blocked domains", + url="http://example.com/domains.txt", + auth=AuthModel( + username="user1", + password="pass123" + ), + recurring=HourlyRecurringModel(hourly={}), + expand_domain=True + ) + ) +) + +payload = domain_list.model_dump(exclude_unset=True) +response = edl.create(payload) +``` + +
+ +### Updating a List + +
+ + +```python +# Using dictionary +update_dict = { + "id": "123e4567-e89b-12d3-a456-426655440000", + "name": "blocked-ips-updated", + "type": { + "ip": { + "description": "Updated blocked IPs", + "url": "http://example.com/blocked-new.txt", + "recurring": {"daily": {"at": "12"}} + } + } +} + +response = edl.update(update_dict) +``` + +
+ +## Best Practices + +1. **List Management** + - Use descriptive names for lists + - Document list purposes in descriptions + - Configure appropriate update intervals + - Monitor list update status + - Review exception lists regularly + +2. **Security** + - Use HTTPS URLs when possible + - Implement proper authentication + - Use client certificates when available + - Regularly rotate credentials + - Monitor list content changes + +3. **Performance** + - Choose appropriate update intervals + - Monitor bandwidth usage + - Use exception lists efficiently + - Consider list size impacts + - Monitor update job status + +## Related Models + +- [AuthModel](../../models/objects/external_dynamic_lists_models.md#Overview) +- [RecurringModels](../../models/objects/external_dynamic_lists_models.md#Overview) +- [TypeModels](../../models/objects/external_dynamic_lists_models.md#Overview) \ No newline at end of file diff --git a/docs/sdk/models/objects/index.md b/docs/sdk/models/objects/index.md index 23f08ef..649b202 100644 --- a/docs/sdk/models/objects/index.md +++ b/docs/sdk/models/objects/index.md @@ -21,6 +21,7 @@ For each configuration object, there are corresponding request and response mode - [Application Models](application_models.md) - [Application Filters Models](application_filters_models.md) - [Application Group Models](application_group_models.md) +- [External Dynamic Lists](external_dynamic_lists_models.md) - [Service Models](service_models.md) - [Service Group Models](service_group_models.md) - [Tag Models](tag_models.md) diff --git a/mkdocs.yml b/mkdocs.yml index a0ca7a1..eb59714 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -42,6 +42,7 @@ nav: - Application: sdk/config/objects/application.md - Application Filters: sdk/config/objects/application_filters.md - Application Group: sdk/config/objects/application_group.md + - External Dynamic Lists: sdk/config/objects/external_dynamic_lists.md - Service: sdk/config/objects/service.md - Service Group: sdk/config/objects/service_group.md - Tag: sdk/config/objects/tag.md @@ -62,6 +63,7 @@ nav: - Application Models: sdk/models/objects/application_models.md - Application Filter Models: sdk/models/objects/application_filters_models.md - Application Group Models: sdk/models/objects/application_group_models.md + - External Dynamic Lists Models: sdk/models/objects/external_dynamic_lists_models.md - Service Models: sdk/models/objects/service_models.md - Service Group Models: sdk/models/objects/service_group_models.md - Tag Models: sdk/models/objects/tag_models.md diff --git a/pyproject.toml b/pyproject.toml index 6511714..f743d3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pan-scm-sdk" -version = "0.3.3" +version = "0.3.4" description = "Python SDK for Palo Alto Networks Strata Cloud Manager." authors = ["Calvin Remsburg "] license = "Apache 2.0"