npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
Zero Standing Privileges (ZSP) is a security model where no user or identity retains persistent privileged access. Instead, elevated access is provisioned dynamically on a just-in-time (JIT) basis and automatically revoked after use. CyberArk implements ZSP through its Secure Cloud Access (SCA) module, which creates ephemeral, scoped roles in cloud environments (AWS, Azure, GCP) that exist only for the duration of a session. The TEA framework -- Time, Entitlements, and Approvals -- governs every privileged access session.
When to Use
- When deploying or configuring implementing zero standing privilege with cyberark capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- CyberArk Identity Security Platform (Privilege Cloud or self-hosted)
- CyberArk Secure Cloud Access (SCA) license
- Cloud provider accounts (AWS, Azure, GCP) with admin access for integration
- ITSM integration (ServiceNow, Jira) for approval workflows
- CyberArk Vault configured with safe management
Core Concepts
TEA Framework (Time, Entitlements, Approvals)
| Component | Description | Configuration |
|---|---|---|
| Time | Duration of the privileged session | Min 15 minutes, max 8 hours, default 1 hour |
| Entitlements | Permissions granted during the session | Dynamically scoped IAM roles/policies |
| Approvals | Authorization workflow before access | Auto-approve, manager approval, or multi-level |
ZSP Architecture
User requests access via CyberArk
│
├── CyberArk evaluates request against policies:
│ ├── Is user eligible for this access?
│ ├── Does the request comply with TEA policies?
│ └── Is approval required?
│
├── [If approval needed] → Route to approver (ITSM/ChatOps)
│
├── Upon approval:
│ ├── CyberArk creates ephemeral IAM role in target cloud
│ ├── Scopes permissions to minimum required entitlements
│ ├── Sets session TTL (time-bound)
│ └── Provisions temporary credentials
│
├── User accesses cloud resources via session
│ ├── All actions logged and recorded
│ └── Session monitored for policy violations
│
└── Session expires:
├── Ephemeral role deleted
├── Temporary credentials revoked
└── Zero standing privileges remainCyberArk Components
| Component | Role |
|---|---|
| Identity Security Platform | Central management and policy engine |
| Privilege Cloud Vault | Stores privileged credentials and keys |
| Secure Cloud Access | Creates/destroys ephemeral cloud roles |
| Endpoint Privilege Manager | Controls local admin and app elevation |
| Privileged Session Manager | Records and monitors privileged sessions |
Workflow
Step 1: Integrate Cloud Providers
AWS Integration:
- Create a CyberArk integration role in AWS IAM
- Configure cross-account trust policy allowing CyberArk to assume roles
- Create IAM policies that define maximum allowed entitlements
- Register AWS accounts in CyberArk SCA
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::CYBERARK_ACCOUNT:role/CyberArkSCARole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "cyberark-external-id"
}
}
}]
}Azure Integration:
- Register CyberArk as an enterprise application in Microsoft Entra ID
- Grant CyberArk application permissions: Directory.ReadWrite.All, RoleManagement.ReadWrite.Directory
- Create custom Azure roles with scoped permissions
- Register Azure subscriptions in CyberArk SCA
GCP Integration:
- Create a service account for CyberArk in GCP
- Grant IAM Admin and Service Account Admin roles
- Configure workload identity federation for cross-cloud access
- Register GCP projects in CyberArk SCA
Step 2: Define Access Policies
Create policies that map job functions to cloud entitlements:
# CyberArk SCA Policy Example
policy_name: "developer-aws-read-access"
description: "Read-only access to AWS production for developers"
target_cloud: "aws"
target_accounts: ["123456789012", "987654321098"]
time_policy:
max_duration: "4h"
default_duration: "1h"
business_hours_only: true
timezone: "America/New_York"
entitlement_policy:
aws_managed_policies:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
deny_actions:
- "iam:*"
- "organizations:*"
- "sts:*"
resource_restrictions:
- "arn:aws:s3:::production-*"
approval_policy:
approval_required: true
approvers:
- type: "manager"
- type: "group"
group: "cloud-security-team"
auto_approve_conditions:
- previous_approved_same_policy: true
within_days: 7
escalation_timeout: "2h"
escalation_approver: "cloud-security-lead"Step 3: Configure Session Monitoring
Set up privileged session recording and real-time monitoring:
- Enable session recording for all ZSP sessions
- Configure keystroke logging for SSH/RDP sessions
- Set up real-time alerts for suspicious activities:
- Attempts to escalate privileges during session
- Access to resources outside policy scope
- Session duration exceeding 2x the normal pattern
- Forward session metadata to SIEM
Step 4: Implement Approval Workflows
Integrate with ITSM tools for access request and approval:
- ServiceNow: CyberArk SCA connector creates ServiceNow tickets for approval
- Slack/Teams: ChatOps bot for quick approvals within messaging platforms
- Jira: Integration for development-related access requests
- Auto-Approval: Configure rules for low-risk, previously approved requests
Step 5: Migrate from Standing Privileges
Phase 1: DISCOVERY (Weeks 1-2)
├── Inventory all standing privileged roles across cloud accounts
├── Map users to their standing role assignments
├── Analyze CloudTrail/activity logs for actual permission usage
└── Identify roles that can be converted to JIT
Phase 2: POLICY CREATION (Weeks 3-4)
├── Create ZSP policies based on actual usage analysis
├── Define TEA parameters for each policy
├── Configure approval workflows
└── Test policies with pilot users
Phase 3: MIGRATION (Weeks 5-8)
├── Assign ZSP policies to pilot group
├── Remove standing privileges from pilot users
├── Monitor for access issues and adjust policies
├── Expand to additional teams incrementally
└── Remove all standing privileges organization-wide
Phase 4: GOVERNANCE (Ongoing)
├── Monthly review of ZSP policy effectiveness
├── Quarterly entitlement optimization
├── Monitor for policy drift or standing privilege re-creation
└── Report ZSP metrics to security leadershipValidation Checklist
- Cloud providers integrated with CyberArk SCA
- TEA policies defined for all privileged access scenarios
- Approval workflows configured and tested
- Session recording and monitoring enabled
- All standing privileged roles identified for migration
- Pilot group successfully using ZSP without standing privileges
- Break-glass procedure defined for emergency access
- SIEM integration receiving session and access logs
- Auto-approval rules configured for low-risk, repeat access
- Organization-wide migration plan approved and scheduled
- KPI tracking: reduction in standing privilege assignments
References
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.7 KB
API Reference: CyberArk Zero Standing Privilege
CyberArk PVWA REST API v2
Authentication
POST /api/auth/CyberArk/Logon
Body: {"username": "admin", "password": "pass"}
Returns: Session token stringKey Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/Safes |
List all safes |
| GET | /api/Safes/{name}/Members |
List safe members and permissions |
| GET | /api/Platforms |
List configured platforms |
| GET | /api/Accounts |
List privileged accounts |
| GET | /api/LiveSessions |
List active privileged sessions |
| POST | /api/Accounts/{id}/CheckIn |
Release exclusive account access |
Safe Member Permissions
| Permission | ZSP Implication |
|---|---|
useAccounts |
Can initiate privileged sessions |
retrieveAccounts |
Can retrieve passwords |
listAccounts |
Can see account inventory |
requestsAuthorizationLevel1 |
Dual-control approval required |
Session Properties
| Field | Description |
|---|---|
User |
Session initiator |
AccountName |
Target privileged account |
Duration |
Session length in seconds |
RemoteMachine |
Target host |
TEA Framework
| Component | API Field | Purpose |
|---|---|---|
| Time | MaxSessionDuration |
Auto-revoke after timeout |
| Entitlements | AllowedPermissions |
Scoped access per session |
| Approvals | requestsAuthorizationLevel |
Require approval workflow |
References
- CyberArk REST API: https://docs.cyberark.com/pam-self-hosted/latest/en/Content/SDK/CyberArk%20REST%20API.htm
- CyberArk Secure Cloud Access: https://docs.cyberark.com/secure-cloud-access/
standards.md1.6 KB
Zero Standing Privilege with CyberArk - Standards Reference
Zero Trust Frameworks
NIST SP 800-207 - Zero Trust Architecture
- Never trust, always verify
- Least privilege access to resources
- Microsegmentation and policy enforcement points
- Dynamic, risk-based access policies
CISA Zero Trust Maturity Model
- Identity pillar: JIT/JEA access for all identities
- Advanced maturity: Automated privilege provisioning/deprovisioning
- Optimal maturity: Continuous verification with ephemeral access
TEA Framework Components
Time
- Session duration: minimum required for task completion
- CyberArk default: 1 hour, configurable 15 min to 8 hours
- Business hours enforcement optional
- Auto-termination on session inactivity
Entitlements
- Principle of least privilege
- Dynamic role creation scoped to specific resources
- Permission boundaries to prevent escalation
- Entitlement analytics for right-sizing
Approvals
- Risk-based approval routing
- Multi-level approval for critical access
- Auto-approval for previously approved, low-risk requests
- ITSM integration (ServiceNow, Jira) for audit trail
Compliance Requirements
SOC 2 - CC6
- CC6.1: Logical access security restricted
- CC6.3: Access authorized, modified, removed timely
- ZSP provides evidence of no standing privileges
PCI DSS v4.0
- 7.2.1: Access limited to least privilege
- 7.2.4: Access reviewed at least every 6 months
- ZSP eliminates the review burden by removing standing access
SOX Section 404
- Separation of duties enforcement
- Access to financial systems must be controlled
- JIT access provides clear audit trail of who accessed what, when
workflows.md3.6 KB
Zero Standing Privilege with CyberArk - Workflows
JIT Access Request Workflow
Developer needs to access AWS production environment
│
├── Opens CyberArk Secure Cloud Access portal
│
├── Selects target: AWS Account "Production" (123456789012)
│
├── Selects policy: "Developer Production Read Access"
│
├── Specifies duration: 2 hours
│
├── Provides justification: "Investigating PROD-1234 latency issue"
│
├── Submits request
│
├── CyberArk evaluates TEA policy:
│ ├── Time: 2 hours within allowed range
│ ├── Entitlements: Read-only production access
│ └── Approval: Manager approval required
│
├── Approval request sent to manager (Slack/email)
│
├── Manager approves
│
├── CyberArk provisions ephemeral IAM role:
│ ├── Creates role with ReadOnlyAccess + resource restrictions
│ ├── Sets session duration to 2 hours
│ └── Generates temporary STS credentials
│
├── Developer accesses AWS console/CLI with temp credentials
│ └── All actions recorded in session log
│
└── After 2 hours: role deleted, credentials revokedStanding Privilege Migration Workflow
Phase 1: DISCOVERY AND ANALYSIS
├── Export all IAM users/roles with standing admin access
├── Analyze CloudTrail logs for actual permission usage
├── Identify which permissions are actually used vs. assigned
├── Calculate right-sized policy for each use case
└── Map standing privileges to CyberArk ZSP policies
Phase 2: POLICY CREATION
├── Create CyberArk SCA policies for each access pattern
├── Define TEA parameters:
│ ├── Maximum session duration per policy
│ ├── Entitlement scope (AWS managed policies + custom)
│ └── Approval requirements (auto vs. manual)
├── Configure approval workflows
└── Test policies with pilot group
Phase 3: PILOT MIGRATION (2-4 weeks)
├── Assign ZSP policies to pilot users
├── Remove standing privileges from pilot users
├── Monitor for access denied errors
├── Adjust policies based on feedback
└── Measure: request volume, approval time, session duration
Phase 4: FULL MIGRATION (4-8 weeks)
├── Migrate teams in waves (1 team per week)
├── Remove standing privileges after ZSP confirmed working
├── Configure auto-detect for new standing privilege creation
└── Report metrics to security leadership
Phase 5: CONTINUOUS GOVERNANCE
├── Weekly: Review and right-size ZSP policies
├── Monthly: Audit for any standing privilege re-creation
├── Quarterly: Entitlement optimization report
└── Alert on: New standing admin roles created outside CyberArkEmergency Break-Glass Workflow
CyberArk SCA unavailable or network issue
│
├── Retrieve break-glass credentials from:
│ ├── Physical safe (sealed envelope)
│ ├── Or secondary vault (Azure Key Vault / AWS Secrets Manager)
│
├── Authenticate with break-glass credentials
│
├── Perform emergency actions
│
├── Document all actions taken
│
└── Post-incident:
├── Rotate break-glass credentials
├── Review session logs for the emergency access
├── File incident report
└── Verify no unauthorized changes madeScripts 2
agent.py7.1 KB
#!/usr/bin/env python3
"""Agent for auditing CyberArk Zero Standing Privilege (ZSP) configuration via REST API."""
import os
import requests
import json
import argparse
from datetime import datetime, timezone
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def authenticate(base_url, username, password, auth_method="CyberArk"):
"""Authenticate to CyberArk PVWA and obtain session token."""
url = f"{base_url}/api/auth/{auth_method}/Logon"
payload = {"username": username, "password": password}
resp = requests.post(url, json=payload, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
token = resp.json().strip('"')
print(f"[*] Authenticated to CyberArk PVWA as {username}")
return {"Authorization": token}
def list_safes(base_url, headers):
"""List all safes to audit access policies."""
url = f"{base_url}/api/Safes"
resp = requests.get(url, headers=headers, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
safes = resp.json().get("value", [])
print(f"[*] Found {len(safes)} safes")
for s in safes[:20]:
print(f" {s['safeName']} (retention: {s.get('numberOfDaysRetention', 'N/A')} days)")
return safes
def audit_safe_members(base_url, headers, safe_name):
"""Audit members and permissions of a specific safe."""
url = f"{base_url}/api/Safes/{safe_name}/Members"
resp = requests.get(url, headers=headers, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
members = resp.json().get("value", [])
findings = []
for m in members:
perms = m.get("permissions", {})
if perms.get("useAccounts") and perms.get("retrieveAccounts"):
if not m.get("memberType") == "Role":
findings.append({
"safe": safe_name, "member": m.get("memberName"),
"issue": "Standing retrieve+use privileges (not JIT)",
"severity": "HIGH",
})
print(f" [!] {m.get('memberName')} has standing access to {safe_name}")
return findings
def list_platforms(base_url, headers):
"""List platforms to verify JIT/ZSP configuration."""
url = f"{base_url}/api/Platforms"
resp = requests.get(url, headers=headers, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
platforms = resp.json().get("Platforms", [])
print(f"[*] Found {len(platforms)} platforms")
for p in platforms:
print(f" {p.get('general', {}).get('name', 'Unknown')} - "
f"Active: {p.get('general', {}).get('active', False)}")
return platforms
def check_jit_sessions(base_url, headers, days=7):
"""Check recent privileged sessions for JIT compliance."""
url = f"{base_url}/api/LiveSessions"
resp = requests.get(url, headers=headers, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
sessions = resp.json().get("LiveSessions", [])
print(f"[*] Active privileged sessions: {len(sessions)}")
long_sessions = []
for s in sessions:
duration = s.get("Duration", 0)
if duration > 3600:
long_sessions.append({
"user": s.get("User"), "target": s.get("AccountName"),
"duration_sec": duration, "severity": "MEDIUM",
})
print(f" [!] Long session: {s.get('User')} -> {s.get('AccountName')} "
f"({duration // 60} min)")
return long_sessions
def audit_accounts_standing_access(base_url, headers):
"""Find privileged accounts with standing (non-JIT) access enabled."""
url = f"{base_url}/api/Accounts"
params = {"limit": 100, "offset": 0}
resp = requests.get(url, headers=headers, params=params, verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true", timeout=30) # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
resp.raise_for_status()
accounts = resp.json().get("value", [])
findings = []
for a in accounts:
props = a.get("platformAccountProperties", {})
if not props.get("JITEnabled", False):
findings.append({
"account": a.get("name"), "safe": a.get("safeName"),
"platform": a.get("platformId"), "issue": "JIT not enabled",
"severity": "HIGH",
})
print(f"[*] Accounts without JIT: {len(findings)}/{len(accounts)}")
return findings
def generate_report(safe_findings, session_findings, account_findings, output_path):
"""Generate ZSP compliance audit report."""
report = {
"audit_date": datetime.now(timezone.utc).isoformat(),
"summary": {
"standing_access_findings": len(safe_findings),
"long_session_findings": len(session_findings),
"non_jit_accounts": len(account_findings),
},
"safe_findings": safe_findings,
"session_findings": session_findings,
"account_findings": account_findings,
}
with open(output_path, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"\n[*] Report saved to {output_path}")
def main():
parser = argparse.ArgumentParser(description="CyberArk Zero Standing Privilege Audit Agent")
parser.add_argument("action", choices=["safes", "audit-safe", "platforms",
"sessions", "accounts", "full-audit"])
parser.add_argument("--url", required=True, help="CyberArk PVWA base URL")
parser.add_argument("--username", required=True)
parser.add_argument("--password", required=True)
parser.add_argument("--safe", help="Specific safe name to audit")
parser.add_argument("-o", "--output", default="zsp_audit.json")
args = parser.parse_args()
headers = authenticate(args.url, args.username, args.password)
if args.action == "safes":
list_safes(args.url, headers)
elif args.action == "audit-safe" and args.safe:
audit_safe_members(args.url, headers, args.safe)
elif args.action == "platforms":
list_platforms(args.url, headers)
elif args.action == "sessions":
check_jit_sessions(args.url, headers)
elif args.action == "accounts":
audit_accounts_standing_access(args.url, headers)
elif args.action == "full-audit":
safes = list_safes(args.url, headers)
sf = []
for s in safes:
sf.extend(audit_safe_members(args.url, headers, s["safeName"]))
sess = check_jit_sessions(args.url, headers)
acct = audit_accounts_standing_access(args.url, headers)
generate_report(sf, sess, acct, args.output)
if __name__ == "__main__":
main()
process.py6.9 KB
#!/usr/bin/env python3
"""
Zero Standing Privilege Audit Tool
Discovers standing privileged access across AWS, Azure, and GCP,
compares against CyberArk ZSP policies, and identifies accounts
that should be migrated to just-in-time access.
Requirements:
pip install boto3 requests
"""
import json
import logging
import sys
from datetime import datetime, timedelta, timezone
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("zsp_audit")
class StandingPrivilegeDiscovery:
"""Discover standing privileged access across cloud environments."""
def __init__(self):
self.findings = []
def discover_aws_standing_privileges(self, profile_name=None):
"""Find AWS IAM users/roles with standing admin access."""
try:
import boto3
except ImportError:
logger.error("boto3 required: pip install boto3")
return []
session = boto3.Session(profile_name=profile_name)
iam = session.client("iam")
admin_policy_arns = {
"arn:aws:iam::aws:policy/AdministratorAccess",
"arn:aws:iam::aws:policy/PowerUserAccess",
"arn:aws:iam::aws:policy/IAMFullAccess",
}
standing = []
# Check IAM users
paginator = iam.get_paginator("list_users")
for page in paginator.paginate():
for user in page["Users"]:
username = user["UserName"]
attached = iam.list_attached_user_policies(UserName=username)
user_policies = {p["PolicyArn"] for p in attached["AttachedPolicies"]}
has_admin = bool(user_policies & admin_policy_arns)
# Check groups
groups = iam.list_groups_for_user(UserName=username)
for group in groups["Groups"]:
grp_policies = iam.list_attached_group_policies(
GroupName=group["GroupName"]
)
for gp in grp_policies["AttachedPolicies"]:
if gp["PolicyArn"] in admin_policy_arns:
has_admin = True
if has_admin:
access_keys = iam.list_access_keys(UserName=username)
active_keys = [
k for k in access_keys["AccessKeyMetadata"]
if k["Status"] == "Active"
]
standing.append({
"cloud": "AWS",
"identity_type": "User",
"identity": username,
"privilege_level": "Admin",
"policies": list(user_policies & admin_policy_arns),
"active_access_keys": len(active_keys),
"created": user["CreateDate"].isoformat(),
"last_used": str(user.get("PasswordLastUsed", "Never")),
"recommendation": "Migrate to CyberArk ZSP",
})
# Check IAM roles (non-service-linked)
role_paginator = iam.get_paginator("list_roles")
for page in role_paginator.paginate():
for role in page["Roles"]:
if role["Path"].startswith("/aws-service-role/"):
continue
role_policies = iam.list_attached_role_policies(
RoleName=role["RoleName"]
)
role_admin_policies = {
p["PolicyArn"] for p in role_policies["AttachedPolicies"]
} & admin_policy_arns
if role_admin_policies:
standing.append({
"cloud": "AWS",
"identity_type": "Role",
"identity": role["RoleName"],
"privilege_level": "Admin",
"policies": list(role_admin_policies),
"created": role["CreateDate"].isoformat(),
"recommendation": "Convert to ephemeral CyberArk SCA role",
})
self.findings.extend(standing)
logger.info(f"Discovered {len(standing)} AWS standing privileged identities")
return standing
def generate_migration_plan(self):
"""Generate a migration plan to move from standing to ZSP."""
if not self.findings:
return {"status": "No standing privileges found"}
plan = {
"generated_at": datetime.now(timezone.utc).isoformat(),
"total_standing_privileges": len(self.findings),
"by_cloud": {},
"by_type": {},
"migration_waves": [],
}
# Categorize
for finding in self.findings:
cloud = finding["cloud"]
plan["by_cloud"][cloud] = plan["by_cloud"].get(cloud, 0) + 1
id_type = finding["identity_type"]
plan["by_type"][id_type] = plan["by_type"].get(id_type, 0) + 1
# Create migration waves
users = [f for f in self.findings if f["identity_type"] == "User"]
roles = [f for f in self.findings if f["identity_type"] == "Role"]
wave_size = 5
wave_num = 1
for i in range(0, len(users), wave_size):
batch = users[i:i + wave_size]
plan["migration_waves"].append({
"wave": wave_num,
"type": "Users",
"identities": [u["identity"] for u in batch],
"count": len(batch),
"suggested_week": f"Week {wave_num}",
})
wave_num += 1
for i in range(0, len(roles), wave_size):
batch = roles[i:i + wave_size]
plan["migration_waves"].append({
"wave": wave_num,
"type": "Roles",
"identities": [r["identity"] for r in batch],
"count": len(batch),
"suggested_week": f"Week {wave_num}",
})
wave_num += 1
return plan
def export_report(self, output_path):
"""Export standing privilege findings and migration plan."""
report = {
"report_title": "Standing Privilege Discovery Report",
"generated_at": datetime.now(timezone.utc).isoformat(),
"findings": self.findings,
"migration_plan": self.generate_migration_plan(),
}
with open(output_path, "w") as f:
json.dump(report, f, indent=2)
logger.info(f"Report exported to {output_path}")
return report
if __name__ == "__main__":
print("=" * 60)
print("Zero Standing Privilege Audit Tool")
print("=" * 60)
print()
print("Usage:")
print(" discovery = StandingPrivilegeDiscovery()")
print(" discovery.discover_aws_standing_privileges(profile='prod')")
print(" plan = discovery.generate_migration_plan()")
print(" discovery.export_report('zsp_report.json')")