Initial commit - 611 cybersecurity skills across all subdomains

This commit is contained in:
mukul975
2026-02-25 10:47:44 +01:00
commit 22a7ab1462
1765 changed files with 280648 additions and 0 deletions
@@ -0,0 +1,134 @@
---
name: None
description: Configure Kubernetes Role-Based Access Control (RBAC) to enforce least-privilege access to cluster resources. This skill covers Role/ClusterRole design, RoleBinding configuration, service account secu
domain: cybersecurity
subdomain: identity-access-management
tags: [iam, identity, access-control, authorization, rbac, kubernetes, k8s]
version: "1.0"
author: mahipal
license: MIT
---
# Implementing RBAC for Kubernetes Cluster
## Overview
Configure Kubernetes Role-Based Access Control (RBAC) to enforce least-privilege access to cluster resources. This skill covers Role/ClusterRole design, RoleBinding configuration, service account security, namespace isolation, and audit logging for multi-tenant Kubernetes environments.
## Objectives
- Design RBAC role hierarchy for multi-tenant clusters
- Create granular Roles and ClusterRoles for different personas
- Configure RoleBindings and ClusterRoleBindings with least privilege
- Secure service accounts and limit their default permissions
- Integrate RBAC with external identity providers (OIDC)
- Audit and monitor RBAC usage with Kubernetes audit logs
## Key Concepts
### RBAC API Objects
1. **Role**: Namespace-scoped permissions (pods, services, deployments within a namespace)
2. **ClusterRole**: Cluster-wide permissions (nodes, namespaces, PVs, CRDs)
3. **RoleBinding**: Grants Role to users/groups/serviceAccounts in a namespace
4. **ClusterRoleBinding**: Grants ClusterRole cluster-wide
### Kubernetes RBAC Verbs
- `get`, `list`, `watch`: Read-only operations
- `create`, `update`, `patch`: Write operations
- `delete`, `deletecollection`: Destructive operations
- `impersonate`: Assume identity of another user
- `escalate`: Modify RBAC roles (highly privileged)
- `bind`: Create RoleBindings (highly privileged)
### Persona-Based Access Model
- **Cluster Admin**: Full cluster management (limit to 2-3 people)
- **Namespace Admin**: Full control within assigned namespace
- **Developer**: Deploy and manage workloads in assigned namespace
- **Viewer**: Read-only access to namespace resources
- **CI/CD Service Account**: Deploy workloads, manage configmaps/secrets
## Implementation Steps
### Step 1: Disable Default Permissive Settings
1. Ensure `--authorization-mode=RBAC` is enabled on API server
2. Remove default cluster-admin bindings from non-admin users
3. Disable auto-mounting of service account tokens in pods
4. Restrict access to default service account in each namespace
### Step 2: Create Custom Roles
```yaml
# Developer Role - namespace scoped
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app-team
name: developer
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "deployments", "services", "configmaps", "jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"] # read secrets but limit create/update
- apiGroups: [""]
resources: ["pods/log", "pods/exec"]
verbs: ["get", "create"]
```
### Step 3: Bind Roles to Users/Groups
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-binding
namespace: app-team
subjects:
- kind: Group
name: "dev-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
```
### Step 4: Secure Service Accounts
- Create dedicated service accounts per application
- Disable automountServiceAccountToken for pods that don't need API access
- Use projected service account tokens with audience and expiry
- Bind minimum required permissions to each service account
### Step 5: OIDC Integration
1. Configure API server with OIDC flags (issuer-url, client-id, username-claim, groups-claim)
2. Map OIDC groups to Kubernetes groups in RoleBindings
3. Use short-lived tokens from OIDC provider
4. Configure kubectl with OIDC authentication plugin
### Step 6: Audit and Monitoring
- Enable Kubernetes audit logging (audit-policy.yaml)
- Log all RBAC-related events (role creation, binding changes)
- Alert on ClusterRoleBinding creation/modification
- Monitor for privilege escalation attempts
- Regular review of who has cluster-admin access
## Security Controls
| Control | NIST 800-53 | Description |
|---------|-------------|-------------|
| Access Control | AC-3 | RBAC enforcement |
| Least Privilege | AC-6 | Minimum necessary Kubernetes permissions |
| Account Management | AC-2 | Service account lifecycle |
| Audit | AU-3 | Kubernetes audit logging |
| Separation of Duties | AC-5 | Namespace isolation |
## Common Pitfalls
- Granting cluster-admin to CI/CD pipelines
- Using wildcard (*) verbs or resources in ClusterRoles
- Not restricting pods/exec which allows container shell access
- Leaving default service account with broad permissions
- Not auditing who can create RoleBindings (privilege escalation vector)
## Verification
- [ ] All users authenticate via OIDC (no static tokens/certs)
- [ ] No unnecessary ClusterRoleBindings to cluster-admin
- [ ] Developers limited to their assigned namespaces
- [ ] Service accounts use least-privilege roles
- [ ] automountServiceAccountToken disabled by default
- [ ] Audit logging captures RBAC changes
- [ ] `kubectl auth can-i` validates expected permissions per persona
@@ -0,0 +1,29 @@
# Kubernetes RBAC Configuration Template
## Namespace RBAC Matrix
| Namespace | Cluster Admin | Namespace Admin | Developer | Viewer | CI/CD SA |
|-----------|--------------|-----------------|-----------|--------|----------|
| production | 2 users | 2 users | 0 | 5 users | 1 SA |
| staging | 2 users | 3 users | 5 users | 3 users | 1 SA |
| development | 2 users | 5 users | 10 users | 0 | 1 SA |
## Role Definitions
| Role Name | Scope | Resources | Verbs | Use Case |
|-----------|-------|-----------|-------|----------|
| namespace-admin | Namespace | * | * (within NS) | Full namespace control |
| developer | Namespace | pods, deployments, services, configmaps | get,list,create,update,delete | Workload management |
| viewer | Namespace | pods, deployments, services, configmaps | get, list, watch | Read-only monitoring |
| secret-reader | Namespace | secrets | get, list | Application secret access |
| ci-deployer | Namespace | deployments, services, configmaps | get,list,create,update,patch | CI/CD pipeline |
## Service Account Inventory
| Service Account | Namespace | Bound Role | automountToken | Purpose |
|-----------------|-----------|------------|----------------|---------|
| | | | | |
## Audit Policy Configuration
- [ ] Log all create/update/delete on RBAC resources (RequestResponse level)
- [ ] Log all pod exec/attach events
- [ ] Log all secret access events
- [ ] Forward audit logs to SIEM
- [ ] Alert on ClusterRoleBinding changes
@@ -0,0 +1,21 @@
# Standards and References - Kubernetes RBAC
## Kubernetes Documentation
- **RBAC Authorization**: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
- **Authenticating**: https://kubernetes.io/docs/reference/access-authn-authz/authentication/
- **Audit Logging**: https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/
## Security Benchmarks
- **CIS Kubernetes Benchmark**: Section 5.1 - RBAC and Service Accounts
- **NSA/CISA Kubernetes Hardening Guide**: https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF
## NIST Standards
- **NIST SP 800-53 Rev 5**: AC-2, AC-3, AC-5, AC-6, AU-3, AU-12
- **NIST SP 800-190**: Application Container Security Guide
## Tools
- **kubectl auth can-i**: Test RBAC permissions
- **rakkess**: Review access matrix for Kubernetes resources
- **rbac-lookup**: Find roles and bindings for users/groups
- **KubiScan**: Scan for risky RBAC configurations
- **kube-bench**: CIS benchmark checker for Kubernetes
@@ -0,0 +1,36 @@
# Kubernetes RBAC Workflows
## Workflow 1: New Team Onboarding
1. Create dedicated namespace for the team
2. Create ResourceQuota and LimitRange for the namespace
3. Create NetworkPolicy to isolate namespace traffic
4. Design Roles based on team member personas (admin, developer, viewer)
5. Create RoleBindings mapped to OIDC groups
6. Create dedicated service accounts for CI/CD
7. Test access with `kubectl auth can-i` for each persona
8. Document namespace ownership and contact
## Workflow 2: RBAC Audit
1. List all ClusterRoleBindings: `kubectl get clusterrolebindings -o wide`
2. Identify bindings to cluster-admin role
3. Review each cluster-admin binding for necessity
4. Check for wildcard permissions in custom roles
5. Verify service accounts have minimum permissions
6. Test pod escape scenarios (exec, privileged containers)
7. Generate compliance report with findings
## Workflow 3: Privilege Escalation Prevention
1. Restrict who can create/modify Roles and RoleBindings
2. Prevent escalate verb usage (only cluster-admin should have it)
3. Block bind verb for non-admin users
4. Prevent impersonate verb usage
5. Use admission controllers (OPA Gatekeeper) for policy enforcement
6. Monitor audit logs for RBAC modification attempts
## Workflow 4: Service Account Hardening
1. List all service accounts: `kubectl get sa --all-namespaces`
2. Identify service accounts with ClusterRole bindings
3. Remove unnecessary ClusterRoleBindings
4. Set automountServiceAccountToken: false in namespace default SA
5. Create per-application service accounts with minimum roles
6. Use projected service account tokens with short expiry
@@ -0,0 +1,285 @@
#!/usr/bin/env python3
"""
Kubernetes RBAC Auditor
Analyzes Kubernetes RBAC configurations to identify overly permissive
roles, dangerous permissions, unnecessary ClusterRoleBindings, and
service account security issues.
"""
import json
import datetime
from typing import Dict, List, Set
from dataclasses import dataclass, field
@dataclass
class K8sRole:
"""Kubernetes Role or ClusterRole."""
name: str
namespace: str # empty for ClusterRole
is_cluster_role: bool
rules: List[Dict] = field(default_factory=list)
# Each rule: {"apiGroups": [...], "resources": [...], "verbs": [...]}
@dataclass
class K8sBinding:
"""Kubernetes RoleBinding or ClusterRoleBinding."""
name: str
namespace: str
is_cluster_binding: bool
role_ref: str
role_ref_kind: str # Role or ClusterRole
subjects: List[Dict] = field(default_factory=list)
# Each subject: {"kind": "User/Group/ServiceAccount", "name": "...", "namespace": "..."}
@dataclass
class RBACFinding:
severity: str
category: str
title: str
description: str
recommendation: str = ""
affected_resources: List[str] = field(default_factory=list)
class KubernetesRBACAuditor:
"""Audits Kubernetes RBAC for security issues."""
DANGEROUS_VERBS = {"*", "escalate", "bind", "impersonate"}
SENSITIVE_RESOURCES = {"secrets", "roles", "clusterroles", "rolebindings",
"clusterrolebindings", "nodes", "persistentvolumes"}
EXEC_RESOURCES = {"pods/exec", "pods/attach"}
def __init__(self):
self.roles: List[K8sRole] = []
self.bindings: List[K8sBinding] = []
self.findings: List[RBACFinding] = []
def load_roles(self, roles: List[Dict]):
for r in roles:
self.roles.append(K8sRole(**r))
def load_bindings(self, bindings: List[Dict]):
for b in bindings:
self.bindings.append(K8sBinding(**b))
def audit_all(self) -> List[RBACFinding]:
self.findings = []
self._audit_wildcard_permissions()
self._audit_dangerous_verbs()
self._audit_cluster_admin_bindings()
self._audit_service_account_bindings()
self._audit_exec_permissions()
self._audit_secret_access()
self._audit_rbac_modification_permissions()
return self.findings
def _audit_wildcard_permissions(self):
for role in self.roles:
for rule in role.rules:
if "*" in rule.get("resources", []) or "*" in rule.get("verbs", []):
scope = "ClusterRole" if role.is_cluster_role else f"Role in {role.namespace}"
self.findings.append(RBACFinding(
severity="critical",
category="Wildcard Permissions",
title=f"Wildcard permissions in {scope} '{role.name}'",
description=f"Resources: {rule.get('resources')}, Verbs: {rule.get('verbs')}. "
"Wildcard grants excessive access violating least privilege.",
recommendation="Replace wildcards with explicit resource and verb lists.",
affected_resources=[role.name]
))
def _audit_dangerous_verbs(self):
for role in self.roles:
for rule in role.rules:
dangerous = set(rule.get("verbs", [])) & self.DANGEROUS_VERBS
if dangerous and "*" not in dangerous: # wildcard already caught
self.findings.append(RBACFinding(
severity="critical",
category="Dangerous Verbs",
title=f"Dangerous verbs in '{role.name}': {', '.join(dangerous)}",
description="escalate/bind allow privilege escalation. "
"impersonate allows identity spoofing.",
recommendation="Remove dangerous verbs. Only cluster-admin should have these.",
affected_resources=[role.name]
))
def _audit_cluster_admin_bindings(self):
cluster_admin_bindings = [
b for b in self.bindings
if b.role_ref == "cluster-admin" and b.is_cluster_binding
]
for binding in cluster_admin_bindings:
for subject in binding.subjects:
if subject.get("kind") == "ServiceAccount":
self.findings.append(RBACFinding(
severity="critical",
category="Cluster Admin",
title=f"ServiceAccount bound to cluster-admin: {subject.get('name')}",
description=f"Service account '{subject.get('name')}' in namespace "
f"'{subject.get('namespace', 'default')}' has full cluster admin access.",
recommendation="Create a dedicated ClusterRole with minimum required permissions.",
affected_resources=[binding.name]
))
elif subject.get("kind") == "Group" and subject.get("name") not in (
"system:masters",
):
self.findings.append(RBACFinding(
severity="high",
category="Cluster Admin",
title=f"Group bound to cluster-admin: {subject.get('name')}",
description=f"All members of group '{subject.get('name')}' have full cluster admin.",
recommendation="Review group membership. Use namespace-scoped roles instead.",
affected_resources=[binding.name]
))
def _audit_service_account_bindings(self):
default_sa_bindings = []
for binding in self.bindings:
for subject in binding.subjects:
if (subject.get("kind") == "ServiceAccount" and
subject.get("name") == "default"):
default_sa_bindings.append(binding)
if default_sa_bindings:
self.findings.append(RBACFinding(
severity="high",
category="Service Account",
title=f"Default service account has {len(default_sa_bindings)} custom bindings",
description="Default service account should not have additional permissions. "
"All pods without explicit SA use the default SA.",
recommendation="Create dedicated service accounts per application. "
"Remove bindings from default SA.",
affected_resources=[b.name for b in default_sa_bindings]
))
def _audit_exec_permissions(self):
for role in self.roles:
for rule in role.rules:
resources = set(rule.get("resources", []))
exec_resources = resources & self.EXEC_RESOURCES
if exec_resources:
self.findings.append(RBACFinding(
severity="high",
category="Pod Exec",
title=f"Pod exec/attach permission in '{role.name}'",
description="pods/exec allows running commands inside containers. "
"This can be used for lateral movement.",
recommendation="Restrict exec access to debugging roles. "
"Monitor exec usage in audit logs.",
affected_resources=[role.name]
))
def _audit_secret_access(self):
for role in self.roles:
for rule in role.rules:
resources = set(rule.get("resources", []))
verbs = set(rule.get("verbs", []))
if "secrets" in resources:
write_verbs = verbs & {"create", "update", "patch", "delete", "*"}
if write_verbs:
self.findings.append(RBACFinding(
severity="high",
category="Secret Access",
title=f"Secret write access in '{role.name}'",
description=f"Write verbs on secrets: {', '.join(write_verbs)}. "
"This allows creating/modifying secrets.",
recommendation="Limit secret write access to operators and CI/CD only.",
affected_resources=[role.name]
))
def _audit_rbac_modification_permissions(self):
rbac_resources = {"roles", "clusterroles", "rolebindings", "clusterrolebindings"}
for role in self.roles:
if role.name in ("cluster-admin", "admin"):
continue # Skip built-in roles
for rule in role.rules:
resources = set(rule.get("resources", []))
if resources & rbac_resources:
verbs = set(rule.get("verbs", []))
write_verbs = verbs & {"create", "update", "patch", "delete", "*"}
if write_verbs:
self.findings.append(RBACFinding(
severity="critical",
category="RBAC Modification",
title=f"RBAC modification permissions in '{role.name}'",
description=f"Can modify RBAC objects: {resources & rbac_resources}. "
"This enables privilege escalation.",
recommendation="Remove RBAC modification permissions from non-admin roles.",
affected_resources=[role.name]
))
def generate_report(self) -> str:
if not self.findings:
self.audit_all()
lines = [
"=" * 70,
"KUBERNETES RBAC AUDIT REPORT",
"=" * 70,
f"Report Date: {datetime.datetime.now().isoformat()}",
f"Roles/ClusterRoles Audited: {len(self.roles)}",
f"Bindings Audited: {len(self.bindings)}",
f"Findings: {len(self.findings)}",
"-" * 70, ""
]
severity_order = {"critical": 0, "high": 1, "medium": 2, "low": 3}
for f in sorted(self.findings, key=lambda x: severity_order.get(x.severity, 5)):
lines.append(f"[{f.severity.upper()}] {f.title}")
lines.append(f" Category: {f.category}")
lines.append(f" {f.description}")
if f.recommendation:
lines.append(f" Fix: {f.recommendation}")
if f.affected_resources:
lines.append(f" Affected: {', '.join(f.affected_resources)}")
lines.append("")
critical = sum(1 for f in self.findings if f.severity == "critical")
lines.append("=" * 70)
lines.append(f"OVERALL: {'FAIL' if critical else 'PASS'}")
lines.append("=" * 70)
return "\n".join(lines)
def main():
auditor = KubernetesRBACAuditor()
auditor.load_roles([
{"name": "developer", "namespace": "app-team", "is_cluster_role": False,
"rules": [
{"apiGroups": ["", "apps"], "resources": ["pods", "deployments", "services"], "verbs": ["get", "list", "create", "update", "delete"]},
{"apiGroups": [""], "resources": ["secrets"], "verbs": ["get", "list"]},
{"apiGroups": [""], "resources": ["pods/exec"], "verbs": ["create"]}
]},
{"name": "ci-deployer", "namespace": "", "is_cluster_role": True,
"rules": [
{"apiGroups": ["*"], "resources": ["*"], "verbs": ["*"]}
]},
{"name": "custom-admin", "namespace": "production", "is_cluster_role": False,
"rules": [
{"apiGroups": ["rbac.authorization.k8s.io"], "resources": ["roles", "rolebindings"], "verbs": ["create", "update", "delete"]},
{"apiGroups": [""], "resources": ["secrets"], "verbs": ["create", "update", "delete"]}
]},
])
auditor.load_bindings([
{"name": "ci-deployer-binding", "namespace": "", "is_cluster_binding": True,
"role_ref": "cluster-admin", "role_ref_kind": "ClusterRole",
"subjects": [{"kind": "ServiceAccount", "name": "ci-deployer", "namespace": "ci-cd"}]},
{"name": "dev-binding", "namespace": "app-team", "is_cluster_binding": False,
"role_ref": "developer", "role_ref_kind": "Role",
"subjects": [{"kind": "Group", "name": "dev-team"}]},
{"name": "default-elevated", "namespace": "app-team", "is_cluster_binding": False,
"role_ref": "developer", "role_ref_kind": "Role",
"subjects": [{"kind": "ServiceAccount", "name": "default", "namespace": "app-team"}]},
])
print(auditor.generate_report())
if __name__ == "__main__":
main()