Skip to content

Client Module

Overview

The SCM (Strata Cloud Manager) client module provides the primary interface for interacting with the Palo Alto Networks Strata Cloud Manager API. It handles authentication, request management, and provides a clean interface for making API calls with proper error handling and Pydantic model validation.

Starting with version 0.3.14, the SCM client supports a unified interface for accessing service objects through attribute-based access, allowing for a more intuitive and streamlined developer experience.

SCM Client

Class Definition

class Scm:
def __init__(
self,
client_id: str,
client_secret: str,
tsg_id: str,
api_base_url: str = "https://api.strata.paloaltonetworks.com",
token_url: str = "https://auth.apps.paloaltonetworks.com/am/oauth2/access_token",
log_level: str = "ERROR"
)

Attributes

Attribute Type Description
api_base_url str Base URL for the API endpoints
token_url str URL for obtaining OAuth tokens
oauth_client OAuth2Client OAuth2 client handling authentication
session requests.Session HTTP session for making requests
logger Logger Logger instance for SDK logging

Client Usage Patterns

The SDK supports two primary usage patterns:

The unified client approach allows you to access all service objects directly through the client instance, providing a more intuitive and streamlined developer experience:

from scm.client import Scm
# Initialize client with your credentialsclient = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id",
# Optional parameters:
# token_url="https://custom.auth.server.com/oauth2/token"
)
# Access services directly through attributesclient.address.create({...})
client.tag.list(folder="Texas")
client.security_rule.get(rule_id)

This pattern offers several advantages: - Reduced code verbosity - Centralized client management - Automatic token refresh handling - No need to create multiple service instances - Consistent interface across all services

Traditional Service Instantiation (Legacy)

You can still use the traditional pattern where service objects are explicitly instantiated:

from scm.client import Scm
from scm.config.objects import Address
# Initialize clientclient = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id",
# Optional parameters:
# token_url="https://custom.auth.server.com/oauth2/token"
)
# Create service instance manuallyaddress_service = Address(client)
# Use the service instanceaddress_service.create({...})

Note

While the traditional pattern is still supported for backward compatibility, it's recommended to use the unified client interface for new development as it provides a more streamlined developer experience and ensures proper token refresh handling.

Available Services

The unified client provides access to all service objects in the SDK through attributes:

Objects

  • client.address - IP addresses, CIDR ranges, and FQDNs for security policies
  • client.address_group - Static or dynamic collections of address objects
  • client.application - Custom application definitions and signatures
  • client.application_filter - Filters for identifying applications by characteristics
  • client.application_group - Logical groups of applications for policy application
  • client.dynamic_user_group - User groups with dynamic membership criteria
  • client.external_dynamic_list - Externally managed lists of IPs, URLs, or domains
  • client.hip_object - Host information profile match criteria
  • client.hip_profile - Endpoint security compliance profiles
  • client.http_server_profile - HTTP server configurations for logging and monitoring
  • client.log_forwarding_profile - Configurations for forwarding logs to external systems
  • client.quarantined_device - Management of devices blocked from network access
  • client.region - Geographic regions for policy control
  • client.schedule - Time-based policies and access control
  • client.service - Protocol and port definitions for network services
  • client.service_group - Collections of services for simplified policy management
  • client.syslog_server_profile - Syslog server configurations for centralized logging
  • client.tag - Resource classification and organization labels

Network

  • client.ike_crypto_profile - IKE crypto profiles for VPN tunnels
  • client.ike_gateway - IKE gateway configurations for VPN tunnel endpoints
  • client.ipsec_crypto_profile - IPsec crypto profiles for VPN tunnel encryption
  • client.nat_rule - Network address translation policies for traffic routing
  • client.security_zone - Security zones for network segmentation

Deployment

  • client.bandwidth_allocation - Bandwidth allocation settings for regions and service nodes
  • client.internal_dns_server - DNS server configurations for domain resolution
  • client.network_location - Geographic network locations for service connectivity
  • client.remote_network - Secure branch and remote site connectivity configurations
  • client.service_connection - Service connections to cloud service providers

Security

  • client.security_rule - Core security policies controlling network traffic
  • client.anti_spyware_profile - Protection against spyware, C2 traffic, and data exfiltration
  • client.decryption_profile - SSL/TLS traffic inspection configurations
  • client.dns_security_profile - Protection against DNS-based threats and tunneling
  • client.url_category - Custom URL categorization for web filtering
  • client.vulnerability_protection_profile - Defense against known CVEs and exploit attempts
  • client.wildfire_antivirus_profile - Cloud-based malware analysis and zero-day protection

Core Methods

HTTP Methods

def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None, **kwargs)

Makes a GET request to the specified endpoint, automatically handling token refresh.

def post(self, endpoint: str, **kwargs)

Makes a POST request to the specified endpoint, automatically handling token refresh.

def put(self, endpoint: str, **kwargs)

Makes a PUT request to the specified endpoint, automatically handling token refresh.

def delete(self, endpoint: str, **kwargs)

Makes a DELETE request to the specified endpoint, automatically handling token refresh.

Job Management Methods

def list_jobs(
self,
limit: int = 100,
offset: int = 0,
parent_id: Optional[str] = None
) -> JobListResponse

Lists jobs with pagination support and optional parent ID filtering. When parent_id is provided, returns only child jobs of the specified parent job.

def get_job_status(self, job_id: str) -> JobStatusResponse

Gets the status of a specific job.

def wait_for_job(
self,
job_id: str,
timeout: int = 300,
poll_interval: int = 10
) -> Optional[JobStatusResponse]

Waits for a job to complete with configurable timeout and polling interval.

Configuration Management Methods

def commit(
self,
folders: List[str],
description: str,
admin: Optional[List[str]] = None,
sync: bool = False,
timeout: int = 300,
) -> CandidatePushResponseModel

Commits configuration changes to SCM with options for synchronous waiting and custom timeout.

Usage Examples

Client Initialization

from scm.client import Scm
# Initialize client with basic configurationclient = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id",
# Optional parameters:
# api_base_url="https://api.custom-domain.com", # Custom API endpoint
# token_url="https://auth.custom-domain.com/oauth2/token", # Custom token endpoint
# log_level="DEBUG" # Change logging level
)

Using the Unified Client Interface

# Create an addressaddress_data = {
"name": "test-address",
"ip_netmask": "192.168.1.0/24",
"description": "Test network address",
"folder": "Texas"
}
new_address = client.address.create(address_data)
print(f"Created address: {new_address.name} with ID: {new_address.id}")
# List tagstags = client.tag.list(folder="Texas")
for tag in tags:
print(f"Tag: {tag.name}, Color: {tag.color}")
# Create a security rulerule_data = {
"name": "allow-internal",
"folder": "Texas",
"source": {"address": ["test-address"]},
"destination": {"address": ["any"]},
"application": ["web-browsing"],
"service": ["application-default"],
"action": "allow"
}
new_rule = client.security_rule.create(rule_data)
print(f"Created rule: {new_rule.name}")
# Commit changesresult = client.commit(
folders=["Texas"],
description="Added test configuration",
sync=True
)
print(f"Commit job ID: {result.job_id}")

Making Raw API Requests

For endpoints not yet covered by dedicated service classes:

# List objects with parametersresponse = client.get(
endpoint="/config/objects/v1/addresses",
params={"folder": "Texas", "limit": 100}
)
# Create new objectresponse = client.post(
endpoint="/config/objects/v1/addresses",
json={
"name": "test-address",
"ip_netmask": "192.168.1.0/24",
"folder": "Texas"
}
)

Job Management

# List recent jobsjobs = client.list_jobs(limit=10)
# Get child jobs of a specific jobchild_jobs = client.list_jobs(parent_id="parent-job-id")
# Wait for job completionstatus = client.wait_for_job("job-id", timeout=600)

Committing Changes

# Commit changes synchronouslyresult = client.commit(
folders=["Texas"],
admin=["all"],
description="Update network configuration",
sync=True,
timeout=300
)

print(f"Commit job ID: {result.job_id}")
# Check commit statusstatus = client.get_job_status(result.job_id)
print(f"Status: {status.data[0].status_str}")

ScmClient Alias

Starting with version 0.3.14, the SDK also provides an ScmClient class as an alias for Scm. This class offers the exact same functionality but with a more explicit name that better describes its purpose:

from scm.client import ScmClient
# Use ScmClient instead of Scm (identical functionality)client = ScmClient(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id",
# Optional parameters:
# token_url="https://custom.auth.server.com/oauth2/token"
)

Error Handling

from scm.exceptions import APIError, AuthenticationError, TimeoutError

try:
result = client.commit(
folders=["Texas"],
admin=["automation@scm-tenant.example.com"],
description="Update configuration",
sync=True
)
except AuthenticationError as e:
print(f"Authentication failed: {e.message}")
except TimeoutError as e:
print(f"Operation timed out: {str(e)}")
except APIError as e:
print(f"API error: {str(e)}")

Best Practices

  1. Use the Unified Client Interface

    • Leverage the attribute-based access for a cleaner code structure
    • Avoid creating separate service instances
    • Utilize a single client instance for all operations
  2. Client Reuse

    • Create a single client instance and reuse it
    • Avoid creating multiple client instances
  3. Error Handling

    • Always wrap API calls in try-except blocks
    • Handle specific exceptions before generic ones
    • Log error details for troubleshooting
  4. Job Management

    • Use sync=True for simpler workflows when waiting for job completion
    • Set appropriate timeouts based on operation complexity
    • Monitor child jobs for complex operations
  5. Logging

    • Use DEBUG level for development and troubleshooting
    • Use ERROR level for production environments