Version: master @ e7f5f7ef (1.9.44) · zscaler/zpa/policies.py
Three related behaviours in one helper. All reproduced directly against the method — no
credentials or network needed.
from zscaler.zpa.policies import PolicySetControllerAPI as P
cases = [
("tuple with empty values", [("app", [])]),
("tuple, two empty slots", [("app", [], [])]),
("doubly operator-prefixed", [("AND", ("AND", ("app", ["72058304855090128"])))]),
("top-level list not tuple", [["app", ["72058304855090128"]]]),
("control: normal", [("app", ["72058304855090128"])]),
]
for label, conds in cases:
print(label, "->", P._create_conditions_v2(P, conds))
Observed:
| input |
result |
[("app", [])] |
emits 1 operand with no values and no entryValues |
[("app", [], [])] |
same |
[("AND", ("AND", ("app", [...])))] |
emits an operand with objectType: "AND" |
[["app", ["..."]]] |
emits nothing at all — silently dropped |
[("app", ["..."])] |
correct |
1 and 2 — operands that match nothing
An operand with an empty values list, and an operand whose objectType is "AND", do not
correspond to any ZPA criterion. Sending either produces a rule that is not scoped the way the
caller described, and the caller gets no indication.
The objectType: "AND" case arises because the helper unwraps exactly one operator prefix; a
second prefix is then read as an object type.
3 — list-shaped conditions are dropped
The top-level element test is isinstance(condition, tuple), so a list of the same shape is
skipped entirely and the method returns nothing. Lists and tuples are otherwise used
interchangeably throughout the SDK's condition handling — convert_v2_to_sdk_format-style
normalisation accepts both — so a caller who builds conditions from JSON (where there are no
tuples) hits this.
Suggested direction
Rather than prescribe: the common thread is that a condition which cannot produce a scoped
operand is emitted or dropped rather than rejected. Validating that each condition yields at
least one operand with a non-empty value payload, and accepting list alongside tuple at the
top level, would close all three. Happy to open a PR if you would like it in this shape.
Version:
master@e7f5f7ef(1.9.44) ·zscaler/zpa/policies.pyThree related behaviours in one helper. All reproduced directly against the method — no
credentials or network needed.
Observed:
[("app", [])]valuesand noentryValues[("app", [], [])][("AND", ("AND", ("app", [...])))]objectType: "AND"[["app", ["..."]]][("app", ["..."])]1 and 2 — operands that match nothing
An operand with an empty
valueslist, and an operand whoseobjectTypeis"AND", do notcorrespond to any ZPA criterion. Sending either produces a rule that is not scoped the way the
caller described, and the caller gets no indication.
The
objectType: "AND"case arises because the helper unwraps exactly one operator prefix; asecond prefix is then read as an object type.
3 — list-shaped conditions are dropped
The top-level element test is
isinstance(condition, tuple), so alistof the same shape isskipped entirely and the method returns nothing. Lists and tuples are otherwise used
interchangeably throughout the SDK's condition handling —
convert_v2_to_sdk_format-stylenormalisation accepts both — so a caller who builds conditions from JSON (where there are no
tuples) hits this.
Suggested direction
Rather than prescribe: the common thread is that a condition which cannot produce a scoped
operand is emitted or dropped rather than rejected. Validating that each condition yields at
least one operand with a non-empty value payload, and accepting
listalongsidetupleat thetop level, would close all three. Happy to open a PR if you would like it in this shape.