mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-01 16:47:42 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,63 @@
|
||||
# API Reference: Implementing Delinea Secret Server for PAM
|
||||
|
||||
## Libraries
|
||||
|
||||
### requests (HTTP client for REST API)
|
||||
- **Install**: `pip install requests`
|
||||
- Used to interact with Secret Server REST API v1
|
||||
|
||||
## Secret Server REST API
|
||||
|
||||
### Authentication
|
||||
- **Endpoint**: `POST /oauth2/token`
|
||||
- **Grant type**: `password`
|
||||
- **Parameters**: `username`, `password`, `domain` (optional)
|
||||
- **Returns**: `access_token` (Bearer token)
|
||||
|
||||
### Secrets API
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v1/secrets` | GET | Search/list secrets |
|
||||
| `/api/v1/secrets/{id}` | GET | Get secret by ID |
|
||||
| `/api/v1/secrets` | POST | Create new secret |
|
||||
| `/api/v1/secrets/{id}` | PUT | Update secret |
|
||||
| `/api/v1/secrets/{id}/change-password` | POST | Trigger password rotation |
|
||||
| `/api/v1/secrets/{id}/check-out` | POST | Check out for exclusive access |
|
||||
| `/api/v1/secrets/{id}/check-in` | POST | Release checked-out secret |
|
||||
| `/api/v1/secrets/{id}/audits` | GET | Audit trail for secret |
|
||||
| `/api/v1/secrets/{id}/fields/{slug}` | GET | Get specific field value |
|
||||
|
||||
### Folders API
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v1/folders` | GET | List folders |
|
||||
| `/api/v1/folders/{id}` | GET | Get folder details |
|
||||
| `/api/v1/folders` | POST | Create folder |
|
||||
|
||||
### Administration API
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v1/users` | GET | List users |
|
||||
| `/api/v1/roles` | GET | List roles |
|
||||
| `/api/v1/secret-templates` | GET | List secret templates |
|
||||
| `/api/v1/configuration/general` | GET | Server configuration |
|
||||
|
||||
## Common Secret Templates
|
||||
- **Windows Account**: Domain, username, password
|
||||
- **Unix Account (SSH)**: Host, username, private key
|
||||
- **SQL Server Account**: Server, database, username, password
|
||||
- **Web Password**: URL, username, password
|
||||
|
||||
## Search Filters
|
||||
- `filter.searchText` -- Keyword search
|
||||
- `filter.folderId` -- Filter by folder
|
||||
- `filter.secretTemplateId` -- Filter by template
|
||||
- `filter.includeSubFolders` -- Include nested folders
|
||||
|
||||
## External References
|
||||
- Secret Server REST API: https://docs.delinea.com/online-help/secret-server/api-scripting/rest-api-reference/
|
||||
- Secret Server SDK: https://github.com/DelineaXPM/python-tss-sdk
|
||||
- PAM Best Practices: https://docs.delinea.com/online-help/secret-server/
|
||||
@@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Delinea Secret Server PAM agent for privileged credential management."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Install requests: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class SecretServerClient:
|
||||
"""Client for Delinea Secret Server REST API."""
|
||||
|
||||
def __init__(self, base_url, username, password, domain=None):
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.session = requests.Session()
|
||||
self.token = self._authenticate(username, password, domain)
|
||||
self.session.headers.update({"Authorization": f"Bearer {self.token}"})
|
||||
|
||||
def _authenticate(self, username, password, domain):
|
||||
"""Authenticate and retrieve OAuth2 bearer token."""
|
||||
url = f"{self.base_url}/oauth2/token"
|
||||
data = {"grant_type": "password", "username": username, "password": password}
|
||||
if domain:
|
||||
data["domain"] = domain
|
||||
resp = self.session.post(url, data=data)
|
||||
resp.raise_for_status()
|
||||
return resp.json()["access_token"]
|
||||
|
||||
def search_secrets(self, search_text=None, folder_id=None, secret_template_id=None):
|
||||
"""Search for secrets with optional filters."""
|
||||
params = {}
|
||||
if search_text:
|
||||
params["filter.searchText"] = search_text
|
||||
if folder_id:
|
||||
params["filter.folderId"] = folder_id
|
||||
if secret_template_id:
|
||||
params["filter.secretTemplateId"] = secret_template_id
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/secrets", params=params)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
def get_secret(self, secret_id):
|
||||
"""Retrieve a secret by ID."""
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/secrets/{secret_id}")
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def create_secret(self, name, template_id, folder_id, fields):
|
||||
"""Create a new secret in the vault."""
|
||||
items = [{"fieldId": fid, "itemValue": val} for fid, val in fields.items()]
|
||||
data = {"name": name, "secretTemplateId": template_id,
|
||||
"folderId": folder_id, "items": items}
|
||||
resp = self.session.post(f"{self.base_url}/api/v1/secrets", json=data)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_secret_templates(self):
|
||||
"""List available secret templates."""
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/secret-templates")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
def get_folders(self, parent_id=None):
|
||||
"""List folders, optionally under a parent."""
|
||||
params = {}
|
||||
if parent_id:
|
||||
params["filter.parentFolderId"] = parent_id
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/folders", params=params)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
def rotate_secret_password(self, secret_id):
|
||||
"""Trigger password rotation for a secret (Remote Password Changing)."""
|
||||
resp = self.session.post(
|
||||
f"{self.base_url}/api/v1/secrets/{secret_id}/change-password")
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_secret_audit(self, secret_id):
|
||||
"""Get audit trail for a specific secret."""
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/secrets/{secret_id}/audits")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
def checkout_secret(self, secret_id):
|
||||
"""Check out a secret for exclusive access."""
|
||||
resp = self.session.post(
|
||||
f"{self.base_url}/api/v1/secrets/{secret_id}/check-out")
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def checkin_secret(self, secret_id):
|
||||
"""Check in a previously checked-out secret."""
|
||||
resp = self.session.post(
|
||||
f"{self.base_url}/api/v1/secrets/{secret_id}/check-in")
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_users(self):
|
||||
"""List all users."""
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/users")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
def get_roles(self):
|
||||
"""List all roles."""
|
||||
resp = self.session.get(f"{self.base_url}/api/v1/roles")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("records", [])
|
||||
|
||||
|
||||
def run_pam_audit(client):
|
||||
"""Run a PAM security audit."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f" DELINEA SECRET SERVER PAM AUDIT")
|
||||
print(f" Generated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
templates = client.get_secret_templates()
|
||||
print(f"--- SECRET TEMPLATES ({len(templates)}) ---")
|
||||
for t in templates[:10]:
|
||||
print(f" [{t['id']}] {t['name']}")
|
||||
|
||||
folders = client.get_folders()
|
||||
print(f"\n--- FOLDERS ({len(folders)}) ---")
|
||||
for f in folders[:10]:
|
||||
print(f" [{f['id']}] {f['folderName']}")
|
||||
|
||||
secrets = client.search_secrets()
|
||||
print(f"\n--- SECRETS ({len(secrets)}) ---")
|
||||
for s in secrets[:10]:
|
||||
print(f" [{s['id']}] {s['name']} (Template: {s.get('secretTemplateName', 'N/A')})")
|
||||
|
||||
users = client.get_users()
|
||||
print(f"\n--- USERS ({len(users)}) ---")
|
||||
for u in users[:10]:
|
||||
print(f" [{u['id']}] {u.get('userName', 'N/A')} - Enabled: {u.get('isDisabled', True)}")
|
||||
|
||||
roles = client.get_roles()
|
||||
print(f"\n--- ROLES ({len(roles)}) ---")
|
||||
for r in roles[:10]:
|
||||
print(f" [{r['id']}] {r['name']}")
|
||||
|
||||
print(f"\n{'='*60}\n")
|
||||
return {"templates": len(templates), "folders": len(folders),
|
||||
"secrets": len(secrets), "users": len(users), "roles": len(roles)}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Delinea Secret Server PAM Agent")
|
||||
parser.add_argument("--url", required=True, help="Secret Server base URL")
|
||||
parser.add_argument("--username", required=True, help="Username")
|
||||
parser.add_argument("--password", required=True, help="Password")
|
||||
parser.add_argument("--domain", help="AD domain (optional)")
|
||||
parser.add_argument("--audit", action="store_true", help="Run PAM audit")
|
||||
parser.add_argument("--search", help="Search secrets by keyword")
|
||||
parser.add_argument("--rotate", type=int, help="Rotate password for secret ID")
|
||||
parser.add_argument("--output", help="Save report to JSON")
|
||||
args = parser.parse_args()
|
||||
|
||||
client = SecretServerClient(args.url, args.username, args.password, args.domain)
|
||||
|
||||
if args.audit:
|
||||
report = run_pam_audit(client)
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
elif args.search:
|
||||
results = client.search_secrets(search_text=args.search)
|
||||
for s in results:
|
||||
print(f" [{s['id']}] {s['name']}")
|
||||
elif args.rotate:
|
||||
result = client.rotate_secret_password(args.rotate)
|
||||
print(json.dumps(result, indent=2))
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user