AnalysisType: rule
Filename: databricks_account_admin_privileged_role_assignment.py
RuleID: "Databricks.Audit.AccountAdminPrivilegedRoleAssignment"
DisplayName: "Databricks Account Admin Privileged Role Assignment"
Enabled: true
Status: Experimental
LogTypes:
- Databricks.Audit
Tags:
- Databricks
- Privilege Escalation
- Persistence
Reports:
MITRE ATT&CK:
- TA0004:T1098 # Account Manipulation
- TA0003:T1136 # Create Account
Severity: Medium
Description: >
Detects when account-level admin privileges are granted in Databricks through direct role
assignments or administrative group membership. Account admins have extensive control across
all workspaces and should be carefully monitored. Successful grants are elevated to HIGH severity.
Runbook: |
1. Query audit logs for all account-level administrative actions by the target principal in the 24 hours after this privilege grant
2. Check if the target principal accessed multiple workspaces or performed bulk operations in the 6 hours after receiving admin rights
3. Find all account admin grants in the past 90 days to identify unusual patterns or privilege escalation chains
Reference: https://github.com/databricks-solutions/cybersec-workspace-detection-app/blob/main/base/detections/event-based/account_admin_privileged_role_assignment.py
SummaryAttributes:
- actor
- target_principal
- principal_type
Tests:
- Name: Set Account Admin Success
ExpectedResult: true
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "setAccountAdmin"
accountId: "12345678-1234-1234-1234-123456789012"
userIdentity:
email: "superadmin@example.com"
sourceIPAddress: "198.51.100.1"
requestParams:
targetUserName: "newadmin@example.com"
response:
statusCode: 200
- Name: Change Account Owner
ExpectedResult: true
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "changeAccountOwner"
userIdentity:
email: "owner@example.com"
requestParams:
targetUserName: "newowner@example.com"
response:
statusCode: 200
- Name: Add to Admin Group
ExpectedResult: true
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "addPrincipalToGroup"
userIdentity:
email: "admin@example.com"
requestParams:
principal: "user@example.com"
targetGroupName: "account-admins"
response:
statusCode: 200
- Name: Failed Admin Grant
ExpectedResult: true
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "setAccountAdmin"
userIdentity:
email: "attacker@example.com"
requestParams:
targetUserName: "attacker@example.com"
response:
statusCode: 403
- Name: Workspace-Level Admin Grant
ExpectedResult: false
Log:
timestamp: 1234567890000
auditLevel: "WORKSPACE_LEVEL"
serviceName: "accounts"
actionName: "setAdmin"
userIdentity:
email: "admin@example.com"
requestParams:
targetUserName: "user@example.com"
- Name: Remove Admin Should Not Alert
ExpectedResult: false
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "removeAdmin"
userIdentity:
email: "admin@example.com"
requestParams:
targetUserName: "user@example.com"
response:
statusCode: 200
- Name: Remove From Admin Group Should Not Alert
ExpectedResult: false
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "removePrincipalFromGroup"
userIdentity:
email: "admin@example.com"
requestParams:
principal: "user@example.com"
targetGroupName: "account-admins"
response:
statusCode: 200
- Name: Non-Admin Group
ExpectedResult: false
Log:
timestamp: 1234567890000
auditLevel: "ACCOUNT_LEVEL"
serviceName: "accounts"
actionName: "addPrincipalToGroup"
userIdentity:
email: "admin@example.com"
requestParams:
principal: "user@example.com"
targetGroupName: "developers"
# ------ paired body: databricks_account_admin_privileged_role_assignment.py ------
from panther_databricks_helpers import (
ADMIN_PRIVILEGE_ACTIONS,
databricks_alert_context,
extract_group_identifier,
extract_target_principal,
get_principal_type,
is_admin_privilege_action,
)
REMOVAL_ACTIONS = ["removeAdmin", "removePrincipalFromGroup"]
def rule(event):
# Must be account-level event
if event.get("auditLevel") != "ACCOUNT_LEVEL":
return False
# Exclude privilege removals — this rule detects grants only
if event.get("actionName") in REMOVAL_ACTIONS:
return False
return is_admin_privilege_action(event)
def severity(event):
status_code = event.deep_get("response", "statusCode")
return "HIGH" if status_code == 200 else "MEDIUM"
def title(event):
action = event.get("actionName", "Unknown Action")
actor = event.deep_get("userIdentity", "email", default="Unknown Actor")
target = extract_target_principal(event) or "Unknown Principal"
status_code = event.deep_get("response", "statusCode")
status = "Granted" if status_code == 200 else "Attempted to grant"
# Check if it's direct admin action or group-based
if action in ADMIN_PRIVILEGE_ACTIONS["direct"]:
return f"{status} account admin privileges to {target} by {actor}"
group = extract_group_identifier(event)
return f"{status} admin group membership ({group}) to {target} by {actor}"
def dedup(event):
target_principal = extract_target_principal(event) or "unknown"
return f"account_admin_privilege_assignment_{target_principal}"
def alert_context(event):
target_principal = extract_target_principal(event)
principal_type = get_principal_type(target_principal) if target_principal else "Unknown"
return databricks_alert_context(
event,
additional_fields={
"privilege_scope": "ACCOUNT_LEVEL",
"target_principal": target_principal,
"principal_type": principal_type,
"target_group": extract_group_identifier(event),
},
)