Module 10 of 13 · DevOps & Platform Engineering · Intermediate

Security & Compliance

Duration: 130 min

Security is foundational to DevOps. This module covers IAM policies, secrets management, threat detection, and compliance as code—essential for protecting infrastructure and applications.

AWS IAM Fundamentals

IAM (Identity and Access Management) controls who can access what resources:

# Create IAM user
aws iam create-user --user-name devops-engineer

# Create access key
aws iam create-access-key --user-name devops-engineer

# Create IAM role
aws iam create-role \
  --role-name ECSTaskRole \
  --assume-role-policy-document file://trust-policy.json

# Attach policy to role
aws iam attach-role-policy \
  --role-name ECSTaskRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

# Create inline policy
aws iam put-role-policy \
  --role-name ECSTaskRole \
  --policy-name S3Access \
  --policy-document file://policy.json

IAM Policies

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "dynamodb:Query",
      "Resource": "arn:aws:dynamodb:us-east-1:123456789:table/Users",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    },
    {
      "Effect": "Deny",
      "Action": "ec2:TerminateInstances",
      "Resource": "*"
    }
  ]
}

AWS Secrets Manager

Secrets Manager securely stores and rotates secrets:

# Create secret
aws secretsmanager create-secret \
  --name prod/db-password \
  --secret-string '{"username":"admin","password":"SecurePassword123"}'

# Get secret
aws secretsmanager get-secret-value \
  --secret-id prod/db-password

# Update secret
aws secretsmanager update-secret \
  --secret-id prod/db-password \
  --secret-string '{"username":"admin","password":"NewPassword456"}'

# Rotate secret
aws secretsmanager rotate-secret \
  --secret-id prod/db-password \
  --rotation-rules AutomaticallyAfterDays=30

Use secrets in applications:

import boto3
import json

secrets_client = boto3.client('secretsmanager')

def get_db_credentials():
    response = secrets_client.get_secret_value(
        SecretId='prod/db-password'
    )
    secret = json.loads(response['SecretString'])
    return secret['username'], secret['password']

username, password = get_db_credentials()

AWS GuardDuty

GuardDuty detects threats using machine learning:

# Enable GuardDuty
aws guardduty create-detector --enable

# List detectors
aws guardduty list-detectors

# Get findings
aws guardduty list-findings \
  --detector-id 12abc34d567e8fa901bc2d3e4f5a6b78

# Get finding details
aws guardduty get-findings \
  --detector-id 12abc34d567e8fa901bc2d3e4f5a6b78 \
  --finding-ids arn:aws:guardduty:us-east-1:123456789:detector/12abc34d567e8fa901bc2d3e4f5a6b78/finding/abc123def456

VPC Security

# Create security group
aws ec2 create-security-group \
  --group-name app-sg \
  --description "Security group for application" \
  --vpc-id vpc-12345

# Allow inbound traffic
aws ec2 authorize-security-group-ingress \
  --group-id sg-12345 \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

# Deny all outbound traffic except HTTPS
aws ec2 revoke-security-group-egress \
  --group-id sg-12345 \
  --protocol -1 \
  --cidr 0.0.0.0/0

aws ec2 authorize-security-group-egress \
  --group-id sg-12345 \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

Network ACLs

# Create network ACL
aws ec2 create-network-acl --vpc-id vpc-12345

# Add inbound rule
aws ec2 create-network-acl-entry \
  --network-acl-id acl-12345 \
  --rule-number 100 \
  --protocol tcp \
  --port-range From=443,To=443 \
  --cidr-block 0.0.0.0/0 \
  --ingress

# Add outbound rule
aws ec2 create-network-acl-entry \
  --network-acl-id acl-12345 \
  --rule-number 100 \
  --protocol tcp \
  --port-range From=443,To=443 \
  --cidr-block 0.0.0.0/0 \
  --egress

Compliance as Code

# Terraform for security compliance
resource "aws_s3_bucket" "secure" {
  bucket = "secure-bucket"
}

# Enable versioning
resource "aws_s3_bucket_versioning" "secure" {
  bucket = aws_s3_bucket.secure.id
  versioning_configuration {
    status = "Enabled"
  }
}

# Enable encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "secure" {
  bucket = aws_s3_bucket.secure.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

# Block public access
resource "aws_s3_bucket_public_access_block" "secure" {
  bucket = aws_s3_bucket.secure.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Enable logging
resource "aws_s3_bucket_logging" "secure" {
  bucket = aws_s3_bucket.secure.id

  target_bucket = aws_s3_bucket.logs.id
  target_prefix = "s3-logs/"
}

Encryption

# Create KMS key
aws kms create-key \
  --description "Key for application encryption"

# Create alias
aws kms create-alias \
  --alias-name alias/app-key \
  --target-key-id arn:aws:kms:us-east-1:123456789:key/12345678-1234-1234-1234-123456789012

# Encrypt data
aws kms encrypt \
  --key-id alias/app-key \
  --plaintext "sensitive data"

# Decrypt data
aws kms decrypt \
  --ciphertext-blob fileb://encrypted-data

Audit Logging

# Enable CloudTrail
aws cloudtrail create-trail \
  --name production-trail \
  --s3-bucket-name cloudtrail-logs

# Start logging
aws cloudtrail start-logging --trail-name production-trail

# Get events
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceName,AttributeValue=my-instance \
  --max-results 10

Security Best Practices

# Pod Security Policy for Kubernetes
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'MustRunAs'
    seLinuxOptions:
      level: "s0:c123,c456"
  fsGroup:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  readOnlyRootFilesystem: false

Vulnerability Scanning

# Scan Docker image with Trivy
trivy image myapp:latest

# Scan Kubernetes manifests
trivy config ./k8s/

# Scan filesystem
trivy fs ./src/

# Generate SBOM (Software Bill of Materials)
trivy image --format cyclonedx myapp:latest > sbom.json

❓ What is AWS IAM used for?

❓ What is AWS Secrets Manager used for?

❓ What does AWS GuardDuty do?

❓ What is the principle of least privilege?

❓ What is CloudTrail used for?

← Previous Continue interactively → Next →

Related Courses