Lab: Implementing Least Privilege and Private Connectivity on AWS
Determine security controls based on requirements
Lab: Implementing Least Privilege and Private Connectivity on AWS
This lab focuses on determining and implementing security controls based on specific requirements: providing an application with private access to data while adhering to the principle of least privilege.
[!WARNING] Remember to run the teardown commands at the end of this lab to avoid ongoing charges to your AWS account.
Prerequisites
- An active AWS Account.
- AWS CLI installed and configured with administrator-level permissions.
- Basic knowledge of VPC concepts (subnets, route tables).
- A terminal or shell environment (bash/zsh preferred).
Learning Objectives
- Provision an S3 bucket with restricted access using IAM policies.
- Configure a VPC Gateway Endpoint to enable private communication between an EC2 instance and S3.
- Implement the principle of least privilege by attaching a specific IAM Role to an EC2 instance.
- Analyze network flows using Security Group rules to minimize the attack surface.
Architecture Overview
Visualizing Security Layers
Below is a representation of the layered security approach used in this lab, from the identity layer down to the network layer.
\begin{tikzpicture} \draw[thick] (0,0) circle (3cm); \draw[thick] (0,0) circle (2cm); \draw[thick] (0,0) circle (1cm); \node at (0,2.5) {Network ACLs}; \node at (0,1.5) {Security Groups}; \node at (0,0.5) {IAM Roles}; \node at (0,-3.5) {\textbf{Defense in Depth Model}}; \end{tikzpicture}
Step-by-Step Instructions
Step 1: Create a Private S3 Bucket
We need a destination for our data that is not accessible via the public internet.
# Generate a unique bucket name
BUCKET_NAME=brainybee-lab-data-$(date +%s)
echo "Your bucket name is: $BUCKET_NAME"
# Create the bucket
aws s3 mb s3://$BUCKET_NAME --region <YOUR_REGION>▶Console Alternative
- Navigate to S3 > Buckets.
- Click Create bucket.
- Enter a unique name (e.g.,
brainybee-lab-data-123). - Keep Block all public access checked.
- Click Create bucket.
Step 2: Create a Least-Privilege IAM Role
Instead of using long-term access keys, we will create a role that only allows s3:ListBucket and s3:GetObject on our specific bucket.
# Create the Trust Policy for EC2
cat <<EOF > trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create the Role
aws iam create-role --role-name BrainyBeeEC2S3Role --assume-role-policy-document file://trust-policy.json
# Create the Permissions Policy
cat <<EOF > permissions-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetObject"],
"Resource": [
"arn:aws:s3:::$BUCKET_NAME",
"arn:aws:s3:::$BUCKET_NAME/*"
]
}
]
}
EOF
# Attach the policy
aws iam put-role-policy --role-name BrainyBeeEC2S3Role --policy-name S3AccessPolicy --policy-document file://permissions-policy.json
# Create the Instance Profile
aws iam create-instance-profile --instance-profile-name BrainyBeeProfile
aws iam add-role-to-instance-profile --instance-profile-name BrainyBeeProfile --role-name BrainyBeeEC2S3Role[!TIP] This policy adheres to the Principle of Least Privilege because it excludes write permissions and limits access only to the necessary bucket.
Step 3: Configure a VPC Gateway Endpoint
To ensure traffic never leaves the AWS network, we will create a Gateway Endpoint for S3 and associate it with our VPC's route table.
# Get your VPC ID and Route Table ID
VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query "Vpcs[0].VpcId" --output text)
RT_ID=$(aws ec2 describe-route-tables --filters "Name=vpc-id,Values=$VPC_ID" --query "RouteTables[0].RouteTableId" --output text)
# Create the S3 Endpoint
aws ec2 create-vpc-endpoint --vpc-id $VPC_ID --service-name com.amazonaws.<YOUR_REGION>.s3 --route-table-ids $RT_ID▶Console Alternative
- Navigate to VPC > Endpoints.
- Click Create endpoint.
- Search for service
com.amazonaws.[region].s3(Type: Gateway). - Select your VPC and the relevant Route Table.
- Click Create endpoint.
Checkpoints
| Verification Step | Command | Expected Result |
|---|---|---|
| Verify IAM Role | aws iam get-role --role-name BrainyBeeEC2S3Role | JSON output showing the role details |
| Verify S3 Privacy | aws s3api get-public-access-block --bucket <YOUR_BUCKET> | BlockPublicAcls: true |
| Verify Endpoint | aws ec2 describe-vpc-endpoints | State should be available |
Teardown
To avoid costs, perform these steps in order:
- Delete the S3 Bucket (Ensure it is empty first):
bash
aws s3 rb s3://$BUCKET_NAME --force - Remove the IAM Role and Profile:
bash
aws iam remove-role-from-instance-profile --instance-profile-name BrainyBeeProfile --role-name BrainyBeeEC2S3Role aws iam delete-instance-profile --instance-profile-name BrainyBeeProfile aws iam delete-role-policy --role-name BrainyBeeEC2S3Role --policy-name S3AccessPolicy aws iam delete-role --role-name BrainyBeeEC2S3Role - Delete the VPC Endpoint:
bash
ENDPOINT_ID=$(aws ec2 describe-vpc-endpoints --query "VpcEndpoints[0].VpcEndpointId" --output text) aws ec2 delete-vpc-endpoints --vpc-endpoint-ids $ENDPOINT_ID
Troubleshooting
| Error | Likely Cause | Solution |
|---|---|---|
Access Denied on S3 sync | IAM policy resource ARN mismatch | Double-check the bucket name in permissions-policy.json. |
| Connection Timeout | Missing VPC Endpoint or Route Table entry | Ensure the Endpoint is associated with the correct Route Table. |
| Role not found | Instance profile propagation delay | Wait 30-60 seconds after creating the IAM role before launching an instance. |
Stretch Challenge
Requirement: Restrict the VPC Endpoint so it only allows access to your specific bucket, preventing users from using this endpoint to exfiltrate data to their own S3 buckets.
▶Show Solution Hint
Apply a VPC Endpoint Policy. Unlike the IAM Role policy (which controls the user/identity), an Endpoint Policy controls the 'pipe'. You can add a policy to the endpoint that specifies:
"Resource": ["arn:aws:s3:::<YOUR_BUCKET_NAME>/*"] and denies all others.
Cost Estimate
- S3: Free tier covers 5GB of storage. Costs are negligible for this lab ($0.023/GB/month after free tier).
- VPC Gateway Endpoints: Free. There is no hourly charge for Gateway Endpoints (S3/DynamoDB).
- IAM: Free.
- EC2 (Optional): If you launch a
t3.micro, it is free tier eligible; otherwise ~$0.01/hour.
Concept Review
Understanding the distinction between types of endpoints is crucial for the SAP-C02 exam.
| Feature | Gateway Endpoint | Interface Endpoint (PrivateLink) |
|---|---|---|
| Supported Services | S3, DynamoDB | Most AWS Services (Kinesis, SNS, etc.) |
| Cost | Free | Hourly charge + per GB data charge |
| Routing | Uses Route Table prefix lists | Uses Private DNS / ENI IP addresses |
| Network | Does not support Direct Connect | Supports Direct Connect & VPN |
[!NOTE] For security controls, always prefer Gateway Endpoints for S3 when cost-effectiveness is a requirement and the traffic originates from within the VPC.