feat(bitdefender): complete Network module (build-out 3/N)

- Completed Network module for bitdefender skill (GravityZone Public API)
- Added getEndpointTags (read), setEndpointLabel (gated), createReconfigureClientTask/reconfigure (gated)
- Confirmed createUninstallTask, getEndpointsByPolicy, getManagedEndpointDetailsByIp, createScanTaskByMailboxes not found under /network
- Fixed endpoint-tags renderer to handle list result (previously crashing _print_kv)
- raw gates setEndpointLabel; reconfigure already gated
- selftest 55 -> 60 passing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 10:32:26 -07:00
parent 2a1ffab19f
commit a254e5f641
5 changed files with 97 additions and 10 deletions

View File

@@ -510,6 +510,38 @@ def cmd_move(client, args):
args.json, _print_kv)
def _print_tags(tags) -> None:
items = tags if isinstance(tags, list) else (tags or {}).get("items", [])
print(f"Endpoint tags: {len(items)}")
for t in items:
print(f" {t}")
def cmd_endpoint_tags(client, args):
_emit(client.get_endpoint_tags(), args.json, _print_tags)
def cmd_set_label(client, args):
if not _gated(f"label endpoint {args.endpoint} = '{args.label}'", args.confirm):
return 3
result = client.set_endpoint_label(args.endpoint, args.label)
_emit({"labeled": args.endpoint, "label": args.label, "result": result},
args.json, _print_kv)
return 0
def cmd_reconfigure(client, args):
extra, rc = _load_json_arg(args.extra_json, "extra-json")
if rc:
return rc
if not _gated(f"reconfigure {len(args.targets)} agent(s): {','.join(args.targets)}",
args.confirm):
return 3
result = client.reconfigure_client(args.targets, extra=extra or None)
_emit({"reconfigured": args.targets, "result": result}, args.json, _print_kv)
return 0
def cmd_make_group(client, args):
result = client.create_custom_group(args.name, args.parent)
_emit({"createdGroup": args.name, "result": result}, args.json, _print_kv)
@@ -524,7 +556,7 @@ DESTRUCTIVE_RAW_PATTERNS = ("delete", "createuninstall", "createremove",
"removefromblocklist", "assignpolicy",
"setpushevent", "createaccount", "updateaccount",
"configurenotif", "createcompany", "suspendcompany",
"activatecompany")
"activatecompany", "setendpointlabel")
def _is_destructive_method(method: str) -> bool:
@@ -770,6 +802,21 @@ def build_parser() -> argparse.ArgumentParser:
sp.add_argument("--name", required=True)
sp.add_argument("--parent")
sub.add_parser("endpoint-tags", help="List endpoint tags.", parents=[common])
sp = sub.add_parser("set-label", help="Set an endpoint's label (gated).",
parents=[common])
sp.add_argument("--endpoint", required=True, help="endpointId.")
sp.add_argument("--label", required=True)
sp.add_argument("--confirm", action="store_true")
sp = sub.add_parser("reconfigure",
help="Reconfigure installed agents (gated).", parents=[common])
sp.add_argument("--targets", nargs="+", required=True, help="Endpoint ids.")
sp.add_argument("--extra-json",
help="JSON reconfigure body (modules/roles/scanMode).")
sp.add_argument("--confirm", action="store_true")
sp = sub.add_parser("raw", help="Call any method directly (power use).",
parents=[common])
sp.add_argument("--module", required=True)
@@ -928,6 +975,9 @@ HANDLERS = {
"scan": cmd_scan,
"move": cmd_move,
"make-group": cmd_make_group,
"endpoint-tags": cmd_endpoint_tags,
"set-label": cmd_set_label,
"reconfigure": cmd_reconfigure,
"raw": cmd_raw,
"delete-endpoint": cmd_delete_endpoint,
"delete-package": cmd_delete_package,