Skip to content

Latest commit

 

History

History
345 lines (287 loc) · 7.95 KB

File metadata and controls

345 lines (287 loc) · 7.95 KB

Code and configuration examples

Patterns you’ll see on SAP-C02 topics. Treat these as templates: swap in your ARNs, account IDs, VPC IDs, and CIDRs. Confirm syntax and behavior in current AWS docs and against your org’s security rules.


1. IAM policy — least privilege for S3 read in one bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListBucketScope",
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::my-app-data-prod",
      "Condition": {
        "StringLike": {
          "s3:prefix": ["tenant-a/*"]
        }
      }
    },
    {
      "Sid": "ObjectReadScope",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:GetObjectVersion"],
      "Resource": "arn:aws:s3:::my-app-data-prod/tenant-a/*"
    }
  ]
}

Prefer IAM roles for workloads; narrow prefixes and KMS grants when buckets use SSE-KMS.


2. KMS key policy — allow use from a specific role (conceptual)

Key policies are resource-based; the CMK must allow both administrators and data-plane users.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow application role to use the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/AppDataProcessorRole"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    }
  ]
}

3. S3 bucket policy — deny unencrypted puts

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-app-data-prod",
        "arn:aws:s3:::my-app-data-prod/*"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    },
    {
      "Sid": "DenyUnencryptedObjectUploads",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::my-app-data-prod/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption": "aws:kms"
        }
      }
    }
  ]
}

Match the encryption condition to SSE-S3 vs SSE-KMS requirements.


4. Trust policy — cross-account role for tooling account

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::222222222222:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "unique-per-integration-id"
        }
      }
    }
  ]
}

Use ExternalId for third-party or cross-org access to reduce confused deputy risk.


5. AWS Organizations SCP — deny regions outside allowlist (example)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyAllOutsideEU",
      "Effect": "Deny",
      "NotAction": [
        "iam:*",
        "organizations:*",
        "support:*",
        "account:*",
        "billing:*",
        "payments:*",
        "tax:*",
        "invoice:*",
        "ce:*",
        "cur:*",
        "pricing:*",
        "route53:*",
        "cloudfront:*",
        "globalaccelerator:*",
        "wafv2:*",
        "shield:*"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": ["eu-west-1", "eu-central-1"]
        }
      }
    }
  ]
}

SCP Deny lists need exceptions for global services and break-glass paths. Test in a sandbox OU first.


6. CloudFormation — VPC with public and private subnets (excerpt)

Single-AZ excerpt for study; production stacks use multiple AZs and NAT per AZ as needed.

AWSTemplateFormatVersion: '2010-09-09'
Description: Minimal VPC pattern for study (add Multi-AZ for production)

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true

  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

Outputs:
  VpcId:
    Value: !Ref VPC
  PublicSubnetId:
    Value: !Ref PublicSubnet
  PrivateSubnetId:
    Value: !Ref PrivateSubnet

Add NAT in public subnets, private route tables, and VPC endpoints for S3/DynamoDB if you want to trim NAT traffic.


7. CodePipeline — high-level stages (YAML concept)

# Illustrative only; real templates add IAM roles, artifacts, and source config
pipeline:
  name: app-release
  stages:
    - name: Source
      actions:
        - provider: CodeCommit | GitHub | CodeStarConnections
    - name: Build
      actions:
        - provider: CodeBuild
    - name: DeployToStaging
      actions:
        - provider: CodeDeploy
          deployment: BlueGreen
    - name: Approval
      actions:
        - provider: Manual
    - name: DeployToProduction
      actions:
        - provider: CodeDeploy

Pair CodeDeploy with ALB target groups for blue/green on EC2 or ECS.


8. AWS CLI — assume role and call S3 (PowerShell-friendly flow)

# Temporary credentials for a role in another account
aws sts assume-role \
  --role-arn arn:aws:iam::111111111111:role/CrossAccountReadOnly \
  --role-session-name local-audit \
  --external-id unique-per-integration-id

# Export AccessKeyId, SecretAccessKey, SessionToken (syntax depends on shell)
# Then:
aws s3 ls s3://my-app-data-prod/ --region eu-west-1

On Windows PowerShell, set $env:AWS_ACCESS_KEY_ID, $env:AWS_SECRET_ACCESS_KEY, $env:AWS_SESSION_TOKEN from the assume-role output.


9. EventBridge rule — pattern matching (illustrative)

{
  "source": ["aws.s3"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["s3.amazonaws.com"],
    "eventName": ["DeleteBucket", "DeleteBucketPolicy"]
  }
}

Route to SNS, Lambda, or SSM Automation; put human approval on destructive automation.


10. Systems Manager Parameter Store — secure string reference in CloudFormation

  DatabasePasswordParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Name: /app/prod/db/password
      Type: String
      Value: 'REPLACE_VIA_PIPELINE_OR_MANUAL'

For production DB secrets, Secrets Manager with rotation and dynamic references usually fits better.


What to try next

  • Small lab: VPC, private EC2, SSM Session Manager (no SSH), S3 VPC endpoint, organization CloudTrail.
  • Config rule plus remediation for an unencrypted EBS volume in a test account.
  • Map each example back to a domain and a pillar in Domain 1.

References