diff --git a/CHANGELOG.md b/CHANGELOG.md index 25eeb45b..7b0ac599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Zscaler Python SDK Changelog +## 1.9.41 (August 6 2026) + +### Notes + +- Python Versions: **v3.9, v3.10, v3.11, v3.12** + +### Enhancements + +* [PR #558](https://github.com/zscaler/zscaler-sdk-python/pull/558) - Added new ZPA Application Segment attributes: + - `guestDetails` + - `stickyEntity` + - `stickyGroup` + - `hbrEnabled` + +* [PR #558](https://github.com/zscaler/zscaler-sdk-python/pull/558) - Added new ZIA URL Filtering and Cloud App Sdettings attributes: + - `enableGoogleAIPrompt` - Indicates whether the use of generative AI prompts with Google AI by users should be categorized and logged + - `enableQuillbotAIPrompt` - Indicates whether the use of generative AI prompts with QuillBot by users should be categorized and logged ## 1.9.40 (August 4 2026) @@ -9,8 +26,8 @@ ### Bug Fixes -* [PR #557](https://github.com/zscaler/zscaler-sdk-python/issues/557) - Added new ZIA URL Category function `list_categories_lite` to return lightweight key-value list of all or custom URL categories. -* [PR #557](https://github.com/zscaler/zscaler-sdk-python/issues/557) - Fixed ZCELL Model `sim_location_groups` to properly parse the `GeoFence` block attribute. +* [PR #557](https://github.com/zscaler/zscaler-sdk-python/pull/557) - Added new ZIA URL Category function `list_categories_lite` to return lightweight key-value list of all or custom URL categories. +* [PR #557](https://github.com/zscaler/zscaler-sdk-python/pull/557) - Fixed ZCELL Model `sim_location_groups` to properly parse the `GeoFence` block attribute. ## 1.9.39 (July 27, 2026) diff --git a/docsrc/zs/guides/release_notes.rst b/docsrc/zs/guides/release_notes.rst index 3e6483c9..8045c9cf 100644 --- a/docsrc/zs/guides/release_notes.rst +++ b/docsrc/zs/guides/release_notes.rst @@ -6,6 +6,27 @@ Release Notes Zscaler Python SDK Changelog ---------------------------- +1.9.41 (August 6 2026) +--------------------------- + +Notes +------- + +- Python Versions: **v3.9, v3.10, v3.11, v3.12** + +Enhancements +------------- + +(`#558 `_) - Added new ZPA Application Segment attributes: + - `guestDetails` + - `stickyEntity` + - `stickyGroup` + - `hbrEnabled` + +(`#558 `_) - Added new ZIA URL Filtering and Cloud App Sdettings attributes: + - `enableGoogleAIPrompt` - Indicates whether the use of generative AI prompts with Google AI by users should be categorized and logged + - `enableQuillbotAIPrompt` - Indicates whether the use of generative AI prompts with QuillBot by users should be categorized and logged + 1.9.40 (August 4 2026) --------------------------- diff --git a/zscaler/zia/models/url_filter_cloud_app_settings.py b/zscaler/zia/models/url_filter_cloud_app_settings.py index dbfab177..5db8ca20 100644 --- a/zscaler/zia/models/url_filter_cloud_app_settings.py +++ b/zscaler/zia/models/url_filter_cloud_app_settings.py @@ -62,6 +62,9 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: config["enableBlockOverrideForNonAuthUser"] if "enableBlockOverrideForNonAuthUser" in config else False ) self.enable_cipa_compliance = config["enableCIPACompliance"] if "enableCIPACompliance" in config else False + self.enable_google_ai_prompt = config["enableGoogleAIPrompt"] if "enableGoogleAIPrompt" in config else False + self.enable_quillbot_ai_prompt = config["enableQuillbotAIPrompt"] if "enableQuillbotAIPrompt" in config else False + else: self.enable_dynamic_content_cat = False self.consider_embedded_sites = False @@ -83,6 +86,8 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: self.enable_newly_registered_domains = False self.enable_block_override_for_non_auth_user = False self.enable_cipa_compliance = False + self.enable_google_ai_prompt = False + self.enable_quillbot_ai_prompt = False def request_format(self) -> Dict[str, Any]: """ @@ -110,6 +115,8 @@ def request_format(self) -> Dict[str, Any]: "enableNewlyRegisteredDomains": self.enable_newly_registered_domains, "enableBlockOverrideForNonAuthUser": self.enable_block_override_for_non_auth_user, "enableCIPACompliance": self.enable_cipa_compliance, + "enableGoogleAIPrompt": self.enable_google_ai_prompt, + "enableQuillbotAIPrompt": self.enable_quillbot_ai_prompt, } parent_req_format.update(current_obj_format) return parent_req_format diff --git a/zscaler/zia/url_filtering.py b/zscaler/zia/url_filtering.py index a35f5d3b..d1e108f7 100644 --- a/zscaler/zia/url_filtering.py +++ b/zscaler/zia/url_filtering.py @@ -497,6 +497,8 @@ def update_url_and_app_settings(self, **kwargs) -> APIResult[dict]: - enable_newly_registered_domains (bool): Block or allow domains identified shortly after registration. - enable_block_override_for_non_auth_user (bool): Allow authenticated users to override website blocks. - enable_cipa_compliance (bool): Enables the predefined CIPA Compliance Rule. + - enable_google_ai_prompt (bool): Categorize and log user prompts sent to Google AI. + - enable_quillbot_ai_prompt (bool): Categorize and log user prompts sent to Quillbot AI. Returns: tuple: diff --git a/zscaler/zpa/models/application_segment.py b/zscaler/zpa/models/application_segment.py index 97af1a0b..7165b5ba 100644 --- a/zscaler/zpa/models/application_segment.py +++ b/zscaler/zpa/models/application_segment.py @@ -71,7 +71,10 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: self.read_only = config["readOnly"] if "readOnly" in config else None self.restriction_type = config["restrictionType"] if "restrictionType" in config else None self.zscaler_managed = config["zscalerManaged"] if "zscalerManaged" in config else None - + self.hbr_enabled = config["hbrEnabled"] if "hbrEnabled" in config else None + self.sticky_entity = config["stickyEntity"] if "stickyEntity" in config else None + self.sticky_group = config["stickyGroup"] if "stickyGroup" in config else None + self.domain_names = ZscalerCollection.form_list(config["domainNames"] if "domainNames" in config else [], str) self.server_groups = [] @@ -84,6 +87,8 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: self.pra_apps = ZscalerCollection.form_list(config["praApps"] if "praApps" in config else [], PRAApps) + self.guest_details = ZscalerCollection.form_list(config["guestDetails"] if "guestDetails" in config else [], GuestDetails) + self.inspection_apps = ZscalerCollection.form_list( config["inspectionApps"] if "inspectionApps" in config else [], InspectionApps ) @@ -168,6 +173,7 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: self.udp_port_ranges = [] self.tcp_port_range = [] self.udp_port_range = [] + self.guest_details = [] self.enabled = None self.double_encrypt = None self.passive_health_enabled = None @@ -200,6 +206,9 @@ def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: self.application_group = None self.zpn_er_id = None self.policy_style = None + self.hbr_enabled = None + self.sticky_entity = None + self.sticky_group = None def request_format(self) -> Dict[str, Any]: """ @@ -254,6 +263,10 @@ def request_format(self) -> Dict[str, Any]: "applicationGroup": self.application_group, "zpnErId": self.zpn_er_id, "policyStyle": self.policy_style, + "hbrEnabled": self.hbr_enabled, + "stickyEntity": self.sticky_entity, + "stickyGroup": self.sticky_group, + "guestDetails": self.guest_details, } @@ -1146,3 +1159,93 @@ def request_format(self) -> Dict[str, Any]: } parent_req_format.update(current_obj_format) return parent_req_format + + +class GuestDetails(ZscalerObject): + """ + A class for GuestDetail objects. + """ + + def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: + """ + Initialize the GuestDetails model based on API response. + + Args: + config (dict): A dictionary representing the GuestDetails configuration. + """ + super().__init__(config) + + if config: + self.federation_id = config["federationId"] if "federationId" in config else None + + if "partnerInfo" in config: + if isinstance(config["partnerInfo"], common.PrivilegedCapabilitiesResource): + self.partner_info = config["partnerInfo"] + elif config["partnerInfo"] is not None: + self.partner_info = common.PartnerInfo(config["partnerInfo"]) + else: + self.partner_info = None + else: + self.partner_info = None + + else: + self.federation_id = None + self.partner_info = None + + def request_format(self) -> Dict[str, Any]: + """ + Return the object as a dictionary in the format expected for API requests. + """ + parent_req_format = super().request_format() + current_obj_format = { + "federationId": self.federation_id, + "partnerInfo": self.partner_info, + } + parent_req_format.update(current_obj_format) + return parent_req_format + + +class PartnerInfo(ZscalerObject): + """ + A class for PartnerInfo objects. + """ + + def __init__(self, config: Optional[Dict[str, Any]] = None) -> None: + """ + Initialize the GuestDetails model based on API response. + + Args: + config (dict): A dictionary representing the PartnerInfo configuration. + """ + super().__init__(config) + + if config: + self.approval_status = config["approvalStatus"] if "approvalStatus" in config else None + self.federation_status = config["federationStatus"] if "federationStatus" in config else None + self.partner_gid = config["partnerGid"] if "partnerGid" in config else None + self.partner_name = config["partnerName"] if "partnerName" in config else None + self.partner_scope_name = config["partnerScopeName"] if "partnerScopeName" in config else None + + else: + self.approval_status = None + self.federation_status = None + self.partner_gid = None + self.partner_name = None + self.partner_scope_name = None + self.partner_info = None + + def request_format(self) -> Dict[str, Any]: + """ + Return the object as a dictionary in the format expected for API requests. + """ + parent_req_format = super().request_format() + current_obj_format = { + "approvalStatus": self.approval_status, + "federationStatus": self.federation_status, + "partnerGid": self.partner_gid, + "partnerName": self.partner_name, + "partnerScopeName": self.partner_scope_name, + "partnerInfo": self.partner_info, + } + parent_req_format.update(current_obj_format) + return parent_req_format