Initial commit
This commit is contained in:
428
skills/infra-security-reviewer/SKILL.md
Normal file
428
skills/infra-security-reviewer/SKILL.md
Normal file
@@ -0,0 +1,428 @@
|
||||
---
|
||||
name: infra-security-reviewer
|
||||
description: |
|
||||
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 |
|
||||
|
||||
```hcl
|
||||
# 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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
# 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 |
|
||||
|
||||
```hcl
|
||||
# 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"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```yaml
|
||||
# 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 |
|
||||
|
||||
```hcl
|
||||
# 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 |
|
||||
|
||||
```hcl
|
||||
# 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
|
||||
Reference in New Issue
Block a user