identity access management

Implementing PAM for Database Access

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.

access-controldatabasedbaiamidentitypamprivileged-access
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

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/readonly

hvac 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

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