Security Audit Demo
This is an illustrative walkthrough. Command outputs, identifiers, thresholds, and findings are sample data, not a live assessment or the plugin defaults. Use the current skill for the execution contract and verify the actual environment before applying a proposed repair.
Security audit walkthrough covering IAM, Network, and Compliance audit results with findings report.
Scenario
Perform a comprehensive security audit on an EKS cluster to identify vulnerabilities and compliance gaps before a security review.
Confirm the intended AWS account, region and Kubernetes context. The command examples below are read-only; apply changes only through the approved remediation process.
Audit Workflow
Step 1: Initiate Security Audit
User request:
Please run a comprehensive security audit on the cluster.
ops-security-audit skill activates and begins systematic security checks.
Phase 1: IAM & Authentication Audit
1.1 IRSA Configuration Check
# List all IRSA-annotated service accounts
kubectl get sa -A -o json | jq '.items[] | select(.metadata.annotations["eks.amazonaws.com/role-arn"] != null) | {namespace:.metadata.namespace, name:.metadata.name, role:.metadata.annotations["eks.amazonaws.com/role-arn"]}'
Output:
{"namespace":"kube-system","name":"aws-load-balancer-controller","role":"arn:aws:iam::123456789012:role/eks-lb-controller-role"}
{"namespace":"kube-system","name":"ebs-csi-controller-sa","role":"arn:aws:iam::123456789012:role/eks-ebs-csi-role"}
{"namespace":"backend","name":"api-service-account","role":"arn:aws:iam::123456789012:role/api-backend-role"}
{"namespace":"analytics","name":"data-processor","role":"arn:aws:iam::123456789012:role/analytics-full-access"}
1.2 Verify Trust Policies
# Check trust policy for suspicious role
aws iam get-role --role-name analytics-full-access --query 'Role.AssumeRolePolicyDocument'
Output:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/ABC123"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"oidc.eks.us-west-2.amazonaws.com/id/ABC123:sub": "system:serviceaccount:*:*"
}
}
}
]
}
FINDING (CRITICAL): Trust policy uses wildcard *:* - any service account can assume this role!
1.3 Check IAM Permissions
# Check for overly permissive policies
aws iam list-attached-role-policies --role-name analytics-full-access
Output:
{
"AttachedPolicies": [
{"PolicyName": "AmazonS3FullAccess", "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"},
{"PolicyName": "AmazonDynamoDBFullAccess", "PolicyArn": "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"}
]
}
FINDING (HIGH): Role has FullAccess policies attached - violates least privilege.
1.4 RBAC Audit
# Find cluster-admin bindings
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | {name:.metadata.name, subjects:.subjects}'
Output:
{
"name": "cluster-admin-binding",
"subjects": [
{"kind": "User", "name": "admin@company.com"},
{"kind": "User", "name": "developer@company.com"},
{"kind": "Group", "name": "system:masters"}
]
}
{
"name": "emergency-access",
"subjects": [
{"kind": "ServiceAccount", "name": "default", "namespace": "kube-system"}
]
}
FINDING (HIGH): Developer user has cluster-admin binding. Default service account has cluster-admin.
1.5 aws-auth ConfigMap Check
kubectl get configmap aws-auth -n kube-system -o yaml
Output:
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789012:role/eks-node-role
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
- rolearn: arn:aws:iam::123456789012:role/admin-role
username: admin
groups:
- system:masters
- rolearn: arn:aws:iam::123456789012:role/developer-role
username: developer
groups:
- system:masters
FINDING (HIGH): Developer role mapped to system:masters group.
Phase 2: Network Security Audit
2.1 Security Group Analysis
# Get cluster security group
CLUSTER_SG=$(aws eks describe-cluster --name prod-cluster --query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' --output text)
# Check inbound rules
aws ec2 describe-security-group-rules --filter Name=group-id,Values=$CLUSTER_SG --query 'SecurityGroupRules[?!IsEgress].{FromPort:FromPort,ToPort:ToPort,Source:CidrIpv4}'
Output:
[
{"FromPort": 443, "ToPort": 443, "Source": "0.0.0.0/0"},
{"FromPort": 22, "ToPort": 22, "Source": "0.0.0.0/0"}
]
FINDING (CRITICAL): SSH (port 22) open to 0.0.0.0/0!
2.2 Network Policy Coverage
# Check namespaces without network policies
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
policies=$(kubectl get networkpolicies -n $ns 2>/dev/null | tail -n +2 | wc -l)
pods=$(kubectl get pods -n $ns 2>/dev/null | tail -n +2 | wc -l)
if [ "$policies" -eq "0" ] && [ "$pods" -gt "0" ]; then
echo "WARNING: $ns has $pods pods but no network policies"
fi
done
Output:
WARNING: backend has 6 pods but no network policies
WARNING: analytics has 4 pods but no network policies
WARNING: monitoring has 8 pods but no network policies
WARNING: default has 2 pods but no network policies
FINDING (MEDIUM): 4 namespaces with workloads lack network policies.
2.3 Cluster Endpoint Access
aws eks describe-cluster --name prod-cluster --query 'cluster.resourcesVpcConfig.{publicAccess:endpointPublicAccess,privateAccess:endpointPrivateAccess,publicCIDRs:publicAccessCidrs}'
Output:
{
"publicAccess": true,
"privateAccess": true,
"publicCIDRs": ["0.0.0.0/0"]
}
FINDING (HIGH): Cluster API endpoint publicly accessible from anywhere.
2.4 VPC Endpoints Check
# Check existing VPC endpoints
VPC_ID=$(aws eks describe-cluster --name prod-cluster --query 'cluster.resourcesVpcConfig.vpcId' --output text)
aws ec2 describe-vpc-endpoints --filters Name=vpc-id,Values=$VPC_ID --query 'VpcEndpoints[].ServiceName'
Output:
[
"com.amazonaws.us-west-2.s3",
"com.amazonaws.us-west-2.ecr.api"
]
FINDING (MEDIUM): Missing recommended VPC endpoints (ecr.dkr, sts, logs, ec2).
Phase 3: Compliance Audit
3.1 Privileged Containers
kubectl get pods -A -o json | jq '[.items[] | select(.spec.containers[].securityContext.privileged==true) | {name:.metadata.name, ns:.metadata.namespace}]'
Output:
[
{"name":"aws-node-abc","ns":"kube-system"},
{"name":"aws-node-def","ns":"kube-system"},
{"name":"debug-pod","ns":"default"},
{"name":"data-processor-xyz","ns":"analytics"}
]
FINDING (HIGH): 2 privileged containers in non-system namespaces (default, analytics).
3.2 Root Containers
Inspect explicit UID settings on regular containers. Container settings override Pod settings; an unspecified UID requires image/runtime inspection. This query does not inspect init or ephemeral containers or observe process UID. See Kubernetes security contexts.
kubectl get pods -A -o json | jq '[
.items[] as $pod
| select(any($pod.spec.containers[];
(.securityContext.runAsUser // $pod.spec.securityContext.runAsUser // null) == 0))
| {name: $pod.metadata.name, ns: $pod.metadata.namespace}
]'
Output:
[
{"name":"api-server-abc","ns":"backend"},
{"name":"worker-def","ns":"backend"},
{"name":"data-processor-xyz","ns":"analytics"},
{"name":"web-app-ghi","ns":"frontend"}
]
FINDING (MEDIUM): 4 Pods contain a regular container explicitly configured with UID 0.
3.3 Pod Security Standards
# Check namespace labels for Pod Security Standards
kubectl get ns -o json | jq '.items[] | select(.metadata.labels["pod-security.kubernetes.io/enforce"] != null) | {name:.metadata.name, enforce:.metadata.labels["pod-security.kubernetes.io/enforce"]}'
Output:
FINDING (MEDIUM): No namespaces have Pod Security Standards enforced.
3.4 Control Plane Logging
aws eks describe-cluster --name prod-cluster --query 'cluster.logging.clusterLogging[?enabled==`true`].types[]'
Output:
["api"]
FINDING (MEDIUM): Only API logging enabled. Missing audit and authenticator logs.
3.5 Envelope Encryption and Key Ownership
aws eks describe-cluster --name prod-cluster \
--query 'cluster.{version:version,encryptionConfig:encryptionConfig}'
Illustrative response:
{"version": "1.29", "encryptionConfig": null}
OBSERVATION (INFORMATIONAL): In this EKS 1.29 sample, encryptionConfig: null
shows no customer-managed KMS configuration; it does not mean Secrets are unencrypted.
EKS 1.28 and later envelope-encrypt all Kubernetes API data. They use an AWS-owned
key encryption key (KEK) by default, or a configured customer-managed KMS key (CMK)
as the KEK. A CMK previously used for Secrets becomes the KEK for all API data.
Verify the actual version and key ownership, and assess any workload-specific CMK
requirement separately. See AWS default envelope encryption.
Item #14 is informational in the report below. No organization-specific CMK requirement has been supplied, so the example does not invent one to justify a finding.
Security Audit Report
# Security Audit Report
## Summary
- **Audit Date**: 2026-03-22 15:00:00 UTC
- **Cluster**: prod-cluster (us-west-2)
- **EKS Version**: 1.29
- **Overall Risk**: CRITICAL
## Executive Summary
This illustrative report records 16 assessed items: 15 security findings and one informational encryption observation.
The security findings comprise 2 Critical, 6 High, 5 Medium, and 2 Low items.
The absence of a customer-managed KMS key is not counted as unencrypted data or an automatic policy violation.
## Assessed Items by Severity
### CRITICAL (2)
| # | Domain | Finding | Risk | Remediation |
|---|--------|---------|------|-------------|
| 1 | IAM | IRSA trust policy with wildcard (`*:*`) | Any pod can assume analytics-full-access role | Scope trust policy to specific namespace:serviceaccount |
| 2 | Network | SSH (22) open to 0.0.0.0/0 | Direct SSH access from internet | Remove through the owning IaC definition; preserve approved administrative access |
### HIGH (6)
| # | Domain | Finding | Risk | Remediation |
|---|--------|---------|------|-------------|
| 3 | IAM | S3/DynamoDB FullAccess policies | Excessive permissions | Create scoped IAM policies |
| 4 | IAM | Developer has cluster-admin | Excessive cluster access | Create limited developer role |
| 5 | IAM | Default SA has cluster-admin | Privilege escalation risk | Remove emergency-access binding |
| 6 | IAM | Developer role in system:masters | Full cluster admin via aws-auth | Map to limited group |
| 7 | Network | API endpoint open to 0.0.0.0/0 | Publicly reachable API endpoint | Plan private endpoint access or verified public egress CIDRs |
| 8 | Compliance | Privileged containers in workloads | Container escape risk | Remove privileged flag |
### MEDIUM (5)
| # | Domain | Finding | Risk | Remediation |
|---|--------|---------|------|-------------|
| 9 | Network | 4 namespaces without NetworkPolicy | Unrestricted pod communication | Deploy default-deny policies |
| 10 | Network | Missing VPC endpoints | Traffic via internet | Add ecr.dkr, sts, logs endpoints |
| 11 | Compliance | 4 Pods with explicit UID 0 in regular containers | Container privilege abuse | Set runAsNonRoot: true |
| 12 | Compliance | No Pod Security Standards | No policy enforcement | Enable PSS restricted mode |
| 13 | Compliance | Incomplete control plane logging | Limited audit trail | Enable audit + authenticator logs |
### INFORMATIONAL (1)
| # | Domain | Observation | Interpretation | Follow-up |
|---|--------|-------------|----------------|-----------|
| 14 | Compliance | No customer-managed KMS configuration | EKS 1.29 has default AWS-owned envelope encryption | Assess a CMK requirement separately; do not infer unencrypted Secrets |
### LOW (2)
| # | Domain | Finding | Risk | Remediation |
|---|--------|---------|------|-------------|
| 15 | Compliance | Debug pod in default namespace | Potential backdoor | Remove debug pod |
| 16 | Network | Unused security groups | Management overhead | Clean up stale SGs |
## Compliance Checklist
| Requirement | Status | Notes |
|-------------|--------|-------|
| No privileged containers in workloads | FAIL | 2 found in default, analytics |
| Regular containers configured as nonroot | FAIL | 4 Pods explicitly configure UID 0 |
| Network policies in all namespaces | FAIL | 4 namespaces missing |
| IRSA/Pod Identity for AWS access | PARTIAL | IRSA used but misconfigured |
| Default API-data envelope encryption | PASS | AWS-owned KMS key applies to this EKS 1.29 sample; no CMK configured |
| Customer-managed key requirement | REVIEW | No organization-specific requirement supplied; assess separately |
| Control plane audit logging | PARTIAL | Only api logs enabled |
| VPC endpoints for AWS services | PARTIAL | 2 of 6 recommended |
| Cluster endpoint private access | PASS | Private access enabled |
| Restricted public access CIDRs | FAIL | Open to 0.0.0.0/0 |
## Remediation Priority
### Immediate (24 hours)
1. Fix IRSA trust policy wildcard (Critical #1)
2. Remove the SSH 0.0.0.0/0 rule through approved IaC (Critical #2)
3. Establish authorized private endpoint access before disabling public access (High #7)
4. Remove privileged flag from workload containers (High #8)
### This Week
5. Create scoped IAM policies (High #3)
6. Fix developer RBAC permissions (High #4, #6)
7. Remove default SA cluster-admin binding (High #5)
8. Deploy default-deny NetworkPolicies (Medium #9)
### This Month
9. Add missing VPC endpoints (Medium #10)
10. Implement Pod Security Standards (Medium #12)
11. Enable full control plane logging (Medium #13)
12. Assess a customer-managed key only if workload policy requires it (Informational #14)
### Ongoing
13. Enforce runAsNonRoot for all workloads (Medium #11)
14. Clean up debug resources (Low #15)
15. Security group hygiene (Low #16)
Approved Remediation and Verification
Critical #1: Fix IRSA Trust Policy
Review this illustrative trust document against the actual OIDC issuer, namespace and service account. Apply an approved IAM/IaC change through the normal reviewed workflow, with rollback and workload verification; this page does not run an IAM update.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/ABC123"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-west-2.amazonaws.com/id/ABC123:aud": "sts.amazonaws.com",
"oidc.eks.us-west-2.amazonaws.com/id/ABC123:sub": "system:serviceaccount:analytics:data-processor"
}
}
}
]
}
Critical #2: Remove SSH Rule
Remove the public SSH rule from its owning CDK/Terraform definition and apply the change through the approved IaC deployment process. Confirm approved administrative access, such as an already-configured AWS Systems Manager Session Manager path, and rollback first. Then inspect the deployed rules so a later deployment cannot silently restore the exposure. Do not substitute an ad-hoc security-group CLI change.
Read-only verification, using the selected group from the audit:
aws ec2 describe-security-group-rules \
--filters "Name=group-id,Values=$CLUSTER_SG"
High #7: Restrict API Endpoint
Use a private-endpoint workflow for this example. Before disabling public access, establish and verify the operators', nodes' and automation's access from the VPC or a connected network, including DNS, routes, scoped security-group rules and IAM/RBAC. Apply the endpoint change through the approved cluster/IaC process with rollback; repeat the read-only check from the established private access path.
aws eks describe-cluster --name prod-cluster \
--query 'cluster.resourcesVpcConfig.{publicAccess:endpointPublicAccess,privateAccess:endpointPrivateAccess,publicCIDRs:publicAccessCidrs}'
publicAccessCidrs controls the public endpoint, not the private endpoint. If an
approved design keeps public access, allow the actual public egress addresses seen
by that endpoint, including NAT egress where applicable; corporate RFC1918 ranges
are not substitutes. See EKS endpoint access
and public access source CIDRs.
Key Points
IRSA wildcard trust policies and SSH open to internet are critical vulnerabilities that could lead to cluster compromise. Remediate immediately.
Multiple findings relate to excessive permissions (FullAccess policies, system:masters mappings). Implement least privilege across IAM and RBAC.
Enable multiple security layers: NetworkPolicies for network segmentation, Pod Security Standards for workload hardening, and encryption for data protection.