Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
Overview
Deploy privileged access management for database systems including Oracle, SQL Server, PostgreSQL, and MySQL. Covers session proxy configuration, credential vaulting, query auditing, dynamic credential generation, and least-privilege database roles.
When to Use
- When deploying or configuring implementing pam for database access 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
- Familiarity with identity access management concepts and tools
- Access to a test or lab environment for safe execution
- Python 3.8+ with required dependencies installed
- Appropriate authorization for any testing activities
Objectives
- Implement comprehensive implementing pam for database access capability
- Establish automated discovery and monitoring processes
- Integrate with enterprise IAM and security tools
- Generate compliance-ready documentation and reports
- Align with NIST 800-53 access control requirements
Security Controls
| Control | NIST 800-53 | Description |
|---|---|---|
| Account Management | AC-2 | Lifecycle management |
| Access Enforcement | AC-3 | Policy-based access control |
| Least Privilege | AC-6 | Minimum necessary permissions |
| Audit Logging | AU-3 | Authentication and access events |
| Identification | IA-2 | User and service identification |
Verification
- Implementation tested in non-production environment
- Security policies configured and enforced
- Audit logging enabled and forwarding to SIEM
- Documentation and runbooks complete
- Compliance evidence generated
Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.8 KB
API Reference: Implementing PAM for Database Access
HashiCorp Vault Database Secrets Engine
# Enable database secrets engine
vault secrets enable database
# Configure PostgreSQL connection
vault write database/config/postgresql \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/mydb" \
allowed_roles="readonly,readwrite" \
username="vault_admin" password="admin_pass"
# Create dynamic credential role
vault write database/roles/readonly \
db_name=postgresql \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" max_ttl="24h"
# Generate dynamic credentials
vault read database/creds/readonlyhvac Python Client
import hvac
client = hvac.Client(url='http://127.0.0.1:8200', token='s.xxx')
creds = client.secrets.database.generate_credentials('readonly')
# creds['data']['username'], creds['data']['password']CyberArk Privileged Cloud API
| Endpoint | Method | Description |
|---|---|---|
/api/Accounts?search=database |
GET | List database accounts |
/api/Accounts/{id}/Password/Retrieve |
POST | Check out password |
/api/Accounts/{id}/CheckIn |
POST | Check in password |
/api/LiveSessions |
GET | List active PSM sessions |
/api/Recordings |
GET | List session recordings |
Privileged Database Roles
| Database | Privileged Roles | Risk |
|---|---|---|
| PostgreSQL | pg_read_all_data, rds_superuser | Critical |
| MySQL | SUPER, ALL PRIVILEGES, GRANT OPTION | Critical |
| Oracle | DBA, SYSDBA, SYSOPER | Critical |
| SQL Server | sysadmin, db_owner, securityadmin | Critical |
Session Proxy Configuration
| Proxy | Protocol | Feature |
|---|---|---|
| CyberArk PSM | RDP/SSH | Full session recording + keystroke logging |
| Teleport | PostgreSQL/MySQL wire | Query audit logging |
| StrongDM | All major DBs | Just-in-time access + approval workflow |
NIST 800-53 PAM Controls
| Control | Description |
|---|---|
| AC-2(4) | Automatic audit of account actions |
| AC-6(1) | Authorize access to security functions |
| AC-6(2) | Non-privileged access for non-security functions |
| AC-6(5) | Privileged accounts for privileged functions only |
| AU-9 | Protection of audit information |
References
- Vault Database Secrets: https://developer.hashicorp.com/vault/docs/secrets/databases
- CyberArk REST API: https://docs.cyberark.com/Product-Doc/OnlineHelp/PAS/Latest/en/Content/WebServices/Implementing%20Privileged%20Account%20Security%20Web%20Services%20SDK.htm
- NIST SP 800-53 AC-6: https://csf.tools/reference/nist-sp-800-53/r5/ac/ac-6/
Scripts 1
agent.py3.9 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""PAM Database Access Agent - audits privileged database sessions and access controls."""
import json
import argparse
import logging
import subprocess
import os
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def query_db_users(db_type, host, admin_user, admin_password):
env = {**os.environ, "PGPASSWORD": admin_password}
if db_type == "postgresql":
cmd = ["psql", "-h", host, "-U", admin_user, "-c",
"SELECT usename, usesuper, usecreatedb, valuntil FROM pg_user;", "--no-align", "-t"]
elif db_type == "mysql":
cmd = ["mysql", "-h", host, "-u", admin_user, f"-p{admin_password}", "-e",
"SELECT user, host, Super_priv, Grant_priv FROM mysql.user;", "-B"]
else:
cmd = ["sqlcmd", "-S", host, "-U", admin_user, "-P", admin_password, "-Q",
"SELECT name, type_desc, is_disabled FROM sys.server_principals WHERE type IN ('S','U');"]
result = subprocess.run(cmd, capture_output=True, text=True, env=env, timeout=120)
return [{"raw": line.strip()} for line in result.stdout.strip().split("\n") if line.strip()]
def audit_shared_accounts(users):
shared_patterns = ["admin", "dba", "root", "sa", "dbadmin", "sysadmin"]
findings = []
for user in users:
raw = user.get("raw", "").lower()
for pattern in shared_patterns:
if pattern in raw:
findings.append({"user": raw, "issue": f"Potential shared account ({pattern})", "severity": "high"})
return findings
def audit_session_logging(db_type, host, admin_user, admin_password):
findings = []
env = {**os.environ, "PGPASSWORD": admin_password}
if db_type == "postgresql":
cmd = ["psql", "-h", host, "-U", admin_user, "-c", "SHOW log_connections;", "--no-align", "-t"]
result = subprocess.run(cmd, capture_output=True, text=True, env=env, timeout=120)
if "off" in result.stdout.lower():
findings.append({"issue": "log_connections disabled", "severity": "high"})
return findings
def check_tls(host, port):
cmd = ["openssl", "s_client", "-connect", f"{host}:{port}", "-brief"]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
return {"tls_enabled": "Protocol" in result.stdout or "TLS" in result.stdout}
except subprocess.TimeoutExpired:
return {"tls_enabled": False}
def generate_report(users, shared, logging_findings, tls):
all_findings = shared + logging_findings
return {
"timestamp": datetime.utcnow().isoformat(),
"total_users": len(users), "shared_account_findings": shared,
"logging_findings": logging_findings, "encryption": tls,
"total_findings": len(all_findings),
}
def main():
parser = argparse.ArgumentParser(description="PAM Database Access Audit Agent")
parser.add_argument("--db-type", required=True, choices=["postgresql", "mysql", "mssql"])
parser.add_argument("--host", required=True)
parser.add_argument("--port", type=int, default=5432)
parser.add_argument("--admin-user", required=True)
parser.add_argument("--admin-password", required=True)
parser.add_argument("--output", default="pam_db_audit_report.json")
args = parser.parse_args()
users = query_db_users(args.db_type, args.host, args.admin_user, args.admin_password)
shared = audit_shared_accounts(users)
logging_f = audit_session_logging(args.db_type, args.host, args.admin_user, args.admin_password)
tls = check_tls(args.host, args.port)
report = generate_report(users, shared, logging_f, tls)
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
logger.info("PAM DB audit: %d users, %d findings", len(users), report["total_findings"])
print(json.dumps(report, indent=2, default=str))
if __name__ == "__main__":
main()
Keep exploring