Files
2025-11-30 08:47:23 +08:00

10 KiB

name, description
name description
infra-security-reviewer WHEN: Infrastructure security audit, secrets management, network policies, compliance checks WHAT: Secrets scanning + Network policies + IAM/RBAC audit + Compliance validation + Security hardening WHEN NOT: Application security → security-scanner, Docker only → docker-reviewer

Infrastructure Security Reviewer Skill

Purpose

Reviews infrastructure configurations for security, compliance, and best practices.

When to Use

  • Infrastructure security audit
  • Secrets management review
  • Network policy review
  • IAM/RBAC audit
  • Compliance check (SOC2, HIPAA, PCI)

Project Detection

  • Terraform files with IAM/security resources
  • Kubernetes NetworkPolicy, RBAC
  • AWS/GCP/Azure security configs
  • .env files, secret references

Workflow

Step 1: Analyze Project

**Cloud**: AWS/GCP/Azure
**IaC**: Terraform/Pulumi
**Secrets**: Vault/AWS Secrets Manager
**Compliance**: SOC2/HIPAA/PCI

Step 2: Select Review Areas

AskUserQuestion:

"Which areas to review?"
Options:
- Full security review (recommended)
- Secrets management
- Network security
- IAM and access control
- Compliance validation
multiSelect: true

Detection Rules

Secrets Management

Check Recommendation Severity
Hardcoded secrets Use secret manager CRITICAL
Secrets in env files Use vault/KMS CRITICAL
No secret rotation Enable auto-rotation HIGH
Secrets in logs Mask in logging CRITICAL
# BAD: Hardcoded secrets
resource "aws_db_instance" "main" {
  password = "SuperSecret123!"  # CRITICAL!
}

variable "api_key" {
  default = "sk-1234567890"  # CRITICAL!
}

# GOOD: Using AWS Secrets Manager
data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = aws_secretsmanager_secret.db_password.id
}

resource "aws_db_instance" "main" {
  password = data.aws_secretsmanager_secret_version.db_password.secret_string
}

# GOOD: Secret rotation
resource "aws_secretsmanager_secret_rotation" "db_password" {
  secret_id           = aws_secretsmanager_secret.db_password.id
  rotation_lambda_arn = aws_lambda_function.rotation.arn

  rotation_rules {
    automatically_after_days = 30
  }
}
# Kubernetes - BAD: Secret in plain text
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: cGFzc3dvcmQxMjM=  # Just base64, not encrypted!

# GOOD: External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: db-secret
  data:
    - secretKey: password
      remoteRef:
        key: prod/db/password

Network Security

Check Recommendation Severity
Public subnet for DB Use private subnet CRITICAL
No network policies Add K8s NetworkPolicy HIGH
Open security groups Restrict to needed ports CRITICAL
No VPC flow logs Enable flow logs MEDIUM
# AWS - GOOD: Network segmentation
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
}

resource "aws_subnet" "private" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "private-${count.index + 1}"
    Type = "private"
  }
}

resource "aws_flow_log" "main" {
  vpc_id          = aws_vpc.main.id
  traffic_type    = "ALL"
  log_destination = aws_cloudwatch_log_group.flow_logs.arn
  iam_role_arn    = aws_iam_role.flow_logs.arn
}

# Security group - least privilege
resource "aws_security_group" "app" {
  name        = "app-sg"
  description = "Application security group"
  vpc_id      = aws_vpc.main.id

  ingress {
    description     = "HTTPS from ALB"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = [aws_security_group.alb.id]
  }

  egress {
    description = "HTTPS to internet"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
# Kubernetes NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-network-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
        - podSelector:
            matchLabels:
              app: ingress-nginx
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: production
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
    - to:  # Allow DNS
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

IAM / Access Control

Check Recommendation Severity
Wildcard permissions Use specific resources CRITICAL
No MFA requirement Require MFA HIGH
Long-lived credentials Use OIDC/roles HIGH
Over-permissive roles Apply least privilege HIGH
# BAD: Overly permissive
resource "aws_iam_policy" "bad" {
  policy = jsonencode({
    Statement = [{
      Effect   = "Allow"
      Action   = "*"
      Resource = "*"
    }]
  })
}

# GOOD: Least privilege
resource "aws_iam_policy" "app" {
  name        = "app-policy"
  description = "Application specific permissions"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "S3ReadWrite"
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject"
        ]
        Resource = [
          "${aws_s3_bucket.app.arn}/*"
        ]
      },
      {
        Sid    = "SecretsRead"
        Effect = "Allow"
        Action = [
          "secretsmanager:GetSecretValue"
        ]
        Resource = [
          aws_secretsmanager_secret.app.arn
        ]
        Condition = {
          StringEquals = {
            "aws:ResourceTag/Environment" = var.environment
          }
        }
      }
    ]
  })
}

# GOOD: OIDC for GitHub Actions
resource "aws_iam_openid_connect_provider" "github" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.github.certificates[0].sha1_fingerprint]
}

resource "aws_iam_role" "github_actions" {
  name = "github-actions-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Federated = aws_iam_openid_connect_provider.github.arn
      }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringEquals = {
          "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
        }
        StringLike = {
          "token.actions.githubusercontent.com:sub" = "repo:myorg/myrepo:*"
        }
      }
    }]
  })
}

Encryption

Check Recommendation Severity
Unencrypted storage Enable encryption at rest HIGH
No TLS Enforce TLS 1.2+ HIGH
Default KMS key Use customer managed key MEDIUM
# GOOD: Encryption at rest
resource "aws_s3_bucket_server_side_encryption_configuration" "app" {
  bucket = aws_s3_bucket.app.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.app.arn
    }
    bucket_key_enabled = true
  }
}

resource "aws_rds_cluster" "main" {
  storage_encrypted = true
  kms_key_id        = aws_kms_key.rds.arn
}

# GOOD: Enforce TLS
resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.main.arn
}

Compliance Checklist

## SOC2 / HIPAA / PCI Compliance

### Access Control
[ ] MFA enforced for all users
[ ] Least privilege IAM policies
[ ] Regular access reviews
[ ] Service accounts with minimal permissions

### Data Protection
[ ] Encryption at rest (S3, RDS, EBS)
[ ] Encryption in transit (TLS 1.2+)
[ ] Customer managed KMS keys
[ ] Key rotation enabled

### Network Security
[ ] VPC with private subnets
[ ] Security groups with least privilege
[ ] Network segmentation
[ ] VPC flow logs enabled

### Logging & Monitoring
[ ] CloudTrail enabled
[ ] GuardDuty enabled
[ ] Config rules for compliance
[ ] Alerting on security events

### Secrets Management
[ ] No hardcoded secrets
[ ] Secrets in Secrets Manager/Vault
[ ] Automatic rotation enabled
[ ] Audit logging for secret access

Response Template

## Infrastructure Security Review Results

**Project**: [name]
**Cloud**: AWS | **IaC**: Terraform

### Secrets Management
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | rds.tf:15 | Hardcoded database password |

### Network Security
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | sg.tf:23 | Security group allows 0.0.0.0/0 |

### IAM
| Status | File | Issue |
|--------|------|-------|
| HIGH | iam.tf:45 | Wildcard permissions in policy |

### Encryption
| Status | File | Issue |
|--------|------|-------|
| HIGH | s3.tf:12 | S3 bucket not encrypted |

### Recommended Actions
1. [ ] Move secrets to AWS Secrets Manager
2. [ ] Restrict security group ingress rules
3. [ ] Apply least privilege to IAM policies
4. [ ] Enable encryption for all storage

Best Practices

  1. Secrets: Never hardcode, use secret managers
  2. Network: Private subnets, strict security groups
  3. IAM: Least privilege, no wildcards
  4. Encryption: At rest and in transit
  5. Audit: Enable logging everywhere

Integration

  • terraform-reviewer: IaC review
  • k8s-reviewer: Kubernetes security
  • security-scanner: Application security