Secure Your AWS Infrastructure
Lock down an AWS environment with IAM, VPC, CloudTrail, and GuardDuty.
Introduction
30 Second Summary
Every application you deploy to the cloud has a front door, a set of keys, and a filing cabinet full of data. Leave any one of these unguarded and the wrong person walks right in.
In this project, you will secure an AWS environment from four angles: network isolation, restricted access, real-time monitoring, and data encryption. By the end, you will have a hardened setup that demonstrates defense-in-depth security principles.
What You'll Build
You can walk an interviewer or team lead through your secured environment, proving each layer blocks a specific threat vector with live evidence that the protection is active.
By the end of this project, you'll have:
- An EC2 instance locked inside a private subnet with no public IP, verified by watching a connection attempt fail against your VPC's network isolation.
- A custom IAM policy scoped to only two S3 actions on a single bucket pattern, demonstrating least-privilege access you can inspect line by line.
- CloudTrail logging every management action and GuardDuty scanning for threats in real time, with proof that your own recent API calls are already captured.
- An encrypted S3 bucket protected by SSE-KMS and all four Block Public Access settings, proven by a failed attempt to make an object public.
- Secret Mission: Generate simulated threat alerts in GuardDuty and practice investigating them like a security analyst responding to a real incident.
Are there any prerequisites?
- You need an AWS account that is Free Tier eligible.
Basic familiarity with navigating the AWS Console (searching for services, clicking through settings) is helpful but not required.
Before We Start
Before diving into the AWS Console, let's lock in what you're about to build and why it matters.
Set Up Your Security Workshop Environment
Every resource you build in this project needs to live in the same AWS region. If resources end up scattered across regions, they cannot communicate with each other and become impossible to find later.
In this step, you will verify your console access, lock in a single region for the entire workshop, and confirm that your account qualifies for Free Tier coverage on the services you will use.
In this step, get ready to:
- Verify AWS Management Console access and set your region to Asia Pacific (Singapore).
- Confirm Free Tier eligibility for the services used in this project.
Verify AWS Console access and set your region
All five steps of this project use resources in a single region. Setting the region now prevents accidental cross-region splits.
- Sign in to the AWS Management Console at https://console.aws.amazon.com.
- In the top-right corner of the console, click the region dropdown (it may show a different region name by default).
- Select Asia Pacific (Singapore) ap-southeast-1 from the list.
- Confirm the region selector now displays Singapore in the top-right corner.
Why ap-southeast-1?
Asia Pacific (Singapore) is a well-established region with full support for every service used in this project. Using a consistent region means your VPC, EC2 instance, S3 bucket, and monitoring tools can all reference each other without cross-region configuration.
You should see the main console dashboard with the search bar across the top and the region selector showing ap-southeast-1.
Can't sign in?
If you see a permissions error or cannot reach the console, confirm you are using the correct account credentials (root user email or IAM user with console access). Check that your password is correct and your account is not suspended.
Help me troubleshoot AWS Console sign-in issues.
Confirm Free Tier eligibility
This project uses services covered by the AWS Free Tier and trial periods. Checking your billing status now ensures you will not be surprised by charges later.
- In the console search bar at the top, type Billing and select Billing and Cost Management from the results.
- On the Billing and Cost Management home page, confirm your account shows current charges or a spending summary. If you see a cost breakdown widget or a $0.00 balance, your account is active and accessible.
What does this project cost?
Every service in this workshop is covered by Free Tier or a free trial:
- EC2: 750 free hours per month of t2.micro or t3.micro instances (Free Tier eligible accounts).
- CloudTrail: the first trail delivering management events is always free.
- GuardDuty: 30-day free trial per region for new activations.
- VPC, IAM, Security Groups, and S3 storage for a test file: no charge or fractions of a cent.
🙋♀️ Seeing an access denied page?
If you are signed in as an IAM user (not the root user), billing access may be disabled for your account. The root user must first enable IAM access to billing under Account Settings in the Billing console. Ask your account administrator to activate IAM access to Billing and Cost Management.
Help me get access to AWS Billing as an IAM user.
Your console now displays ap-southeast-1 in the region selector, and you can navigate to Billing and Cost Management without errors. You are ready to start building.
Your environment is locked in. Next up, you will build a custom VPC with a private subnet and launch an EC2 instance that is completely unreachable from the public internet.
Build a Locked-Down Network with a Private EC2 Instance
Your console is set up and your region is locked to ap-southeast-1. Now it's time to build the first layer of your secure environment: a network that keeps your compute resources completely hidden from the public internet.
When you launch an EC2 instance in the default VPC, AWS automatically gives it a public IP address. Anyone on the internet can attempt to reach it. In this step, you'll build a custom VPC with a private subnet that has no route to the internet, then place an instance inside it.
In this step, get ready to:
- Create a custom VPC with public and private subnets.
- Launch an EC2 instance in the private subnet with a restricted Security Group.
- Verify the instance is completely unreachable from the internet.
Create a custom VPC with public and private subnets
A VPC (Virtual Private Cloud) is your own isolated network inside AWS. By creating one from scratch, you control exactly which parts are internet-facing and which are hidden.
- In the AWS Console search bar at the top, type VPC and select VPC from the results.
- Choose Create VPC.
- Select VPC and more.
What does VPC and more do?
This option creates your VPC along with subnets, route tables, and an internet gateway all at once. It saves you from building each piece individually.
- Set Name tag auto-generation to security-workshop.
- Set IPv4 CIDR block to 10.0.0.0/16.
- Set Number of Availability Zones to 1.
- Set Number of public subnets to 1.
- Set Number of private subnets to 1.
- Set NAT gateways to None.
- Set VPC endpoints to None.
- Choose Create VPC and wait for all resources to show a green success status.
You should see a workflow page confirming that your VPC, subnets, route tables, and internet gateway were all created successfully.
Why no NAT gateway?
A NAT gateway allows instances in a private subnet to reach the internet for outbound traffic. By deliberately leaving it out, you prove that the private subnet is truly isolated. No traffic can flow in or out to the public internet.
This also keeps costs at $0. NAT gateways incur hourly charges.
Launch an EC2 instance in the private subnet
Now you'll place a compute resource inside that locked-down private subnet. The instance will have no public IP and a Security Group with zero inbound rules, making it invisible to the outside world.
- In the console search bar, type EC2 and select EC2.
- Choose Launch instances.
- In the Name field, enter secure-internal-server.
- Under Application and OS Images, select Amazon Linux (it should show a Free Tier eligible badge).
- Under Instance type, select t2.micro (Free Tier eligible). If t2.micro is not available, select t3.micro instead.
- Under Key pair (login), select Proceed without a key pair.
Why no key pair?
Key pairs are used for SSH access. Since this instance lives in a fully private subnet with no internet path, SSH from outside is impossible anyway. Skipping the key pair reinforces that no one should connect to it directly.
- Under Network settings, choose Edit.
- Set VPC to security-workshop-vpc.
- Set Subnet to the private subnet (security-workshop-subnet-private1-ap-southeast-1a).
- Confirm Auto-assign public IP shows Disable.
- Under Firewall (security groups), select Create security group.
- Set Security group name to internal-only-sg.
- Set Description to Allows no inbound traffic from the internet.
- Delete the default SSH inbound rule by clicking Remove next to it. You should have zero inbound rules remaining.
What does an empty Security Group do?
A Security Group with no inbound rules blocks all incoming traffic. Even if someone discovered the instance's private IP, no connection would be accepted. This is the principle of deny-by-default.
- Leave all other settings as default and choose Launch instance.
You should see a success banner confirming your instance is launching.
Don't see t2.micro?
If your account was created after July 15, 2025, t2.micro may not appear as Free Tier eligible. Select t3.micro instead. It is Free Tier eligible for newer accounts.
Verify network isolation
The instance is running, but is it actually hidden from the internet? You'll now prove that no one can reach it from outside.
- In the left navigation of the EC2 console, choose Instances.
- Select secure-internal-server from the list.
- Confirm the Instance state column shows Running.
- Under the Details tab, find Public IPv4 address. It should show a dash, meaning no public IP is assigned.
Before you try the next step, what do you think will happen if you attempt to connect to this instance using EC2 Instance Connect?
- With the instance selected, choose Connect at the top of the page.
- On the EC2 Instance Connect tab, choose Connect.
The connection fails. You'll see an error indicating EC2 Instance Connect cannot reach your instance. This is the expected result.
The instance has no public IP and no internet route. EC2 Instance Connect requires a network path to the instance, and your private subnet deliberately has none. This proves your network isolation is working exactly as designed.
Instance not showing Running?
It can take 1-2 minutes for the instance to fully launch. Refresh the instances list by clicking the refresh icon at the top of the table. If it stays in a Pending state for more than 5 minutes, check that you selected the correct subnet and VPC.
Help me debug my EC2 instance launch
Your first security layer is locked in. You have an EC2 instance that is completely invisible to the public internet. Next up, you'll add the second layer: restricting what actions users can perform with least-privilege IAM policies.
Create a Least-Privilege IAM Policy and Role
Your EC2 instance is locked inside a private subnet with zero inbound access from the internet. Network isolation is your first layer of defense.
Without restricted IAM permissions, any user or service with broad access could still override your security controls or reach resources they should never touch. In this step, you will create a least-privilege policy that grants only the minimum permissions needed for a specific task.
In this step, get ready to:
- Create a custom IAM policy scoped to read-only S3 access on a specific bucket pattern.
- Create an IAM role with EC2 as the trusted entity and attach the policy.
- Review the resulting permissions to confirm least-privilege scope.
Create a custom IAM policy
An IAM policy is a JSON document that defines exactly which AWS actions are allowed or denied, and on which resources. You will create one that permits only reading objects from S3 buckets whose name starts with a specific prefix.
- Navigate to the IAM Console by typing "IAM" in the console search bar at the top and selecting IAM from the results.
- In the left navigation pane, choose Policies.
- Click Create policy.
- In the Policy editor section, choose the JSON option.
- Select all default content in the editor and delete it, then paste in this least-privilege policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadOnly",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::security-workshop-data-*",
"arn:aws:s3:::security-workshop-data-*/*"
]
}
]
}
What does this policy do?
This policy has a single permission statement with three key parts.
- Action limits what the holder can do to just two operations: s3:GetObject (download a file) and s3:ListBucket (list the contents of a bucket). No writing, deleting, or creating buckets is allowed.
- Resource restricts those actions to only buckets whose name starts with security-workshop-data-. The first ARN targets the bucket itself (for listing) and the second targets objects inside it (for downloading).
- Version is set to 2012-10-17, the current IAM policy language version.
- Click Next.
- On the Review and create page, enter SecurityWorkshopS3ReadOnly in the Policy name field.
- In the Description field, enter Grants read-only access to S3 buckets prefixed with security-workshop-data.
- Click Create policy.
A green success banner confirms the policy was created. You can now find SecurityWorkshopS3ReadOnly in your policies list.
Don't see a success banner?
- Check for red validation errors in the JSON editor. A missing comma, extra bracket, or misspelled key will prevent creation.
- Ensure you selected the JSON option and not the Visual editor, which structures the policy differently.
- If the policy name is already taken, add a number suffix (e.g. SecurityWorkshopS3ReadOnly2).
Still stuck? Help me fix my IAM policy creation error.
Create an IAM role and attach the policy
A policy on its own does nothing until it is attached to an identity. An IAM role is an identity that an AWS service (like EC2) can assume to temporarily gain the permissions defined in the attached policy.
- In the left navigation pane of the IAM Console, choose Roles.
- Click Create role.
- For Trusted entity type, choose AWS service.
- Under Use case, choose EC2. This allows EC2 instances to assume the role.
- Click Next.
- In the search box on the Add permissions page, type SecurityWorkshopS3ReadOnly.
- Select the checkbox next to SecurityWorkshopS3ReadOnly.
- Click Next.
- In the Role name field, enter SecurityWorkshopEC2Role.
- Click Create role.
A success banner confirms the role was created. The console also creates an instance profile with the same name behind the scenes, which allows EC2 instances to use this role.
Can't find your policy in the search?
- Make sure you are searching in the Add permissions step, not in a different step of the wizard.
- Check that the policy name is spelled exactly as SecurityWorkshopS3ReadOnly (case-sensitive).
- If you added a number suffix during creation, search for that exact name instead.
Need more help? Help me find my policy when creating an IAM role.
Review the least-privilege scope
Before you move on, take a moment to confirm the role has exactly the permissions you intended and nothing more.
Before you look, predict: what actions should this role be able to perform, and on which resources?
- In the Roles list, search for and click SecurityWorkshopEC2Role.
- In the Permissions tab, expand the SecurityWorkshopS3ReadOnly policy to see the full permissions.
The policy shows only s3:GetObject and s3:ListBucket on resources matching arn:aws:s3:::security-workshop-data-*. This role cannot write, delete, create buckets, or access any other AWS service. This is least privilege in action.
Why is this important?
AWS best practice is to grant only the permissions required to perform a task. By scoping this policy to a specific bucket name prefix and only two read actions, even if someone compromises the role, the blast radius is contained to read-only access on a narrow set of resources.
Compare this to an AdministratorAccess policy that grants full access to every service. A compromised admin role gives an attacker the keys to your entire AWS account.
Your access controls are in place. Next up, you will enable real-time monitoring so every API call in your account is recorded and suspicious activity triggers alerts.
Enable CloudTrail and GuardDuty for Security Monitoring
In the previous step, you created an IAM policy and role that restricts access to only the specific S3 actions your EC2 instance needs. You now have two strong layers of defense: network isolation and restricted permissions.
However, you currently have no way to know if someone attempts to bypass these controls. Without monitoring, a breach could go undetected indefinitely. In this step, you will enable CloudTrail and GuardDuty to add real-time visibility across your entire account.
In this step, get ready to:
- View existing CloudTrail Event History and create a permanent trail for audit logging.
- Enable GuardDuty for automated threat detection.
- Verify that monitoring is actively capturing your actions in real time.
View CloudTrail Event History and create a trail
AWS already logs your management actions for 90 days by default in Event History. However, this history is not permanently stored and cannot trigger alerts. Creating a trail stores every API call permanently in an S3 bucket.
- Navigate to the CloudTrail Console by typing CloudTrail in the console search bar and selecting the service.
- In the left navigation, choose Event history.
- Observe your recent actions listed here (CreateVpc, RunInstances, CreatePolicy, CreateRole).
Why can I already see events?
CloudTrail logs management events by default and provides 90 days of event history viewable in the console at no charge. The limitation is that this history is not permanently stored and cannot be exported for long-term audit or used to trigger automated alerts. Creating a trail solves both problems.
Now create a trail to store these events permanently.
- In the left navigation, choose Trails, then choose Create trail.
- For Trail name, enter security-workshop-trail.
- Under Storage location, select Create new S3 bucket and accept the auto-generated bucket name.
- Under Log file SSE-KMS encryption, leave it set to Enabled and select New.
- In the AWS KMS Alias field, enter security-workshop-key.
- Leave the default settings for CloudWatch Logs (do not enable it).
- Choose Next.
- On the Choose log events page, keep the default Management events selected.
- Confirm that both Read and Write are checked under Management events.
- Choose Next.
- On the Review and create page, review your settings and choose Create trail.
Your new trail appears on the Trails page. Logging is turned on automatically.
What does this trail do?
The trail captures every management API call (Read and Write) across all enabled regions and delivers the log files to the S3 bucket CloudTrail just created. The logs are encrypted with SSE-KMS using the customer-managed KMS key you just created.
Your first trail delivering management events is always free. Only the S3 storage for log files incurs minimal charges (pennies per month).
🙋♀️ Trail creation failed?
If you see a permissions error about S3, confirm your IAM user has the s3:PutEncryptionConfiguration permission. Admin accounts have this by default.
If the bucket name is taken, accept the auto-generated name rather than typing a custom one. Help me troubleshoot my CloudTrail trail creation
Enable Amazon GuardDuty
CloudTrail records what happened. GuardDuty analyzes those records (plus VPC Flow Logs and DNS query logs) to detect threats automatically.
- Navigate to the GuardDuty Console by typing GuardDuty in the console search bar and selecting the service.
- If you see a welcome page, choose Get started.
- On the Welcome to GuardDuty page, choose Enable GuardDuty.
You should see a banner confirming your 30-day free trial has started. GuardDuty immediately begins analyzing CloudTrail management events, VPC Flow Logs, and DNS query logs for threats.
What is GuardDuty scanning?
GuardDuty continuously monitors three foundational data sources: CloudTrail management events, VPC Flow Logs, and DNS query logs. It uses machine learning and threat intelligence to detect suspicious activity like unusual API calls, unauthorized access attempts, or communication with known malicious IP addresses.
The 30-day free trial covers all foundational threat detection. After 30 days, charges apply based on event volume.
🙋♀️ Don't see the Get started button?
If GuardDuty is already enabled in your account (perhaps by an organization administrator), you will see the Summary dashboard instead of the welcome page. This means GuardDuty is already active and you can proceed to the next substep.
Help me figure out if GuardDuty is already enabled
Verify monitoring is active
Both services are now running. Let's confirm they are capturing your actions.
- Navigate back to the CloudTrail Console.
- In the left navigation, choose Event history.
Before you search, what event name do you think will prove CloudTrail is recording your trail creation?
- In the Lookup attributes dropdown, search for CreateTrail.
You should see the CreateTrail event from moments ago. This proves CloudTrail is capturing your actions in real time.
- Now navigate back to the GuardDuty Console.
- In the left navigation, choose Findings.
- Confirm the page shows no findings (this is good news, it means no threats have been detected).
- Check the Summary page to confirm the service is active.
Why are there no findings?
An empty Findings page means GuardDuty has not detected any threats. This is the desired state for a new, secure account. In the Secret Mission, you will generate sample findings to practice reading threat alerts.
Can't find the CreateTrail event?
Make sure you are searching by Event name in the Lookup attributes dropdown, not by a different attribute.
If the event does not appear immediately, wait 1-2 minutes and refresh the page. CloudTrail events can take a moment to appear in Event History.
Help me find my CreateTrail event in CloudTrail
You now have full visibility into your AWS account. CloudTrail logs every management API call to a permanent S3 bucket, and GuardDuty actively scans for threats using those logs plus VPC Flow Logs and DNS data. Next up, you will protect your S3 data with encryption and blocked public access.
Protect S3 Data with Encryption and Blocked Public Access
Your monitoring can now detect unauthorized access attempts across the account. But what about the data itself?
If someone gains access to the storage layer, encryption and public access blocks are the last line of defense. In this step, you will create an S3 bucket with server-side encryption and prove that the guardrails actively block attempts to expose your data.
In this step, get ready to:
- Create an S3 bucket with all four Block Public Access settings enabled.
- Upgrade the bucket's default encryption from SSE-S3 to SSE-KMS.
- Prove the public access guardrail works by attempting to make an object public and watching it fail.
Create an S3 bucket with Block Public Access enabled
Every S3 bucket created today gets default encryption (SSE-S3) and all four Block Public Access settings enabled automatically. You will confirm those defaults are in place and then upgrade the encryption to a stronger option.
- Navigate to the S3 Console by searching S3 in the top search bar.
- Choose Create bucket.
- Under Bucket type, confirm General purpose is selected.
- Under Bucket namespace, select Global namespace.
- In the Bucket name field, enter security-workshop-data- followed by your 12-digit AWS account ID (for example, security-workshop-data-123456789012).
- Confirm that AWS Region is set to Asia Pacific (Singapore) ap-southeast-1.
- Scroll down to Block Public Access settings for this bucket.
- Confirm all four checkboxes are enabled (they are on by default).
What are the four Block Public Access settings?
These four settings form a safety net that overrides any policy or ACL that would otherwise expose your data to the public internet:
- Block public access granted through new ACLs.
- Block public access granted through any ACLs.
- Block public access granted through new bucket or access point policies.
- Restrict public and cross-account access granted through any bucket or access point policies.
Even if someone attaches a permissive policy later, these settings override it and keep the bucket private.
Upgrade encryption to SSE-KMS
By default, S3 encrypts every object with SSE-S3 (AES-256). Upgrading to SSE-KMS adds an extra layer: each encryption request goes through AWS Key Management Service, which logs key usage in CloudTrail and supports fine-grained access policies.
- On the same Create bucket page, scroll down to Default encryption.
- Change the Encryption type from Server-side encryption with Amazon S3 managed keys (SSE-S3) to Server-side encryption with AWS Key Management Service keys (SSE-KMS).
- Under AWS KMS key, choose Choose from your AWS KMS keys and select the aws/s3 key (AWS managed).
- Leave Bucket Key enabled.
- Choose Create bucket.
You should see a green success banner confirming the bucket was created.
Why the aws/s3 managed key?
AWS offers customer-managed keys for maximum control, but they add key rotation and policy management overhead. The aws/s3 managed key gives you KMS-level audit logging without the complexity of managing your own key.
🙋♀️ Don't see the bucket?
If the creation failed, check that your bucket name is globally unique. S3 bucket names share a global namespace, so another AWS account may already use the same name. Double-check you appended your own 12-digit account ID.
help me troubleshoot why my S3 bucket creation failed
Verify encryption and public access protection
The bucket exists. Now you will confirm the encryption and Block Public Access settings are active, then deliberately test the guardrail.
- Open the newly created bucket from the S3 bucket list.
- Choose the Properties tab.
- Scroll to Default encryption and confirm it shows Server-side encryption with AWS Key Management Service keys (SSE-KMS) with the aws/s3 key.
- Choose the Permissions tab.
- Confirm Block public access shows On for all four settings.
Both protections are confirmed. Next, upload a test file to verify that encryption is applied to objects automatically.
- Choose the Objects tab.
- Choose Upload.
- Choose Add files and select any small text file from your computer (a simple .txt file works).
- Choose Upload, then choose Close when the upload completes.
- Select the uploaded file by clicking its name.
- Scroll down to Server-side encryption settings in the file's properties.
- Confirm it shows AWS Key Management Service key (SSE-KMS).
Your test file is encrypted with KMS. Now for the final proof: try to make this object public and watch the guardrail stop you.
Before you try this, what do you think will happen when you attempt to make the object public?
- Select the uploaded file using the checkbox next to it.
- Choose Actions, then choose Make public using ACL.
The action fails with an error. This is exactly what you want to see. The combination of Block Public Access and disabled ACLs prevents anyone from accidentally exposing objects to the internet, even if they have console access to the bucket.
Why did the action fail?
Two layers blocked the attempt. Block Public Access overrides any new public ACL, and the default Object Ownership setting (Bucket owner enforced) disables ACLs entirely. Together these ensure that no one can accidentally or maliciously make your data public through ACLs.
🙋♀️ Don't see the Make public using ACL option?
Depending on your console version, the option may appear grayed out or may not appear at all when ACLs are disabled. This is the same protection in action. If the option is missing entirely, that confirms the bucket is properly locked down.
help me verify that my S3 bucket's public access protections are working
You have now secured your data at rest with SSE-KMS encryption and proven that Block Public Access actively stops anyone from exposing objects to the public internet. This is your final layer of defense-in-depth: network isolation, least-privilege IAM, real-time monitoring, and now encrypted, access-controlled storage.
Your secured AWS environment is complete. Up next, a secret mission challenges you to generate simulated threats and practice reading security alerts like a real incident responder.
Secret mission
Generate and Investigate GuardDuty Sample Findings
Real threats will eventually appear in GuardDuty. Practice investigating simulated security alerts now so you know exactly how to interpret and respond when a real one fires.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. Most of these resources are covered by the AWS Free Tier or a 30-day trial, but some will incur charges if left running indefinitely.
Cost warning
Your EC2 instance (t2.micro/t3.micro) is Free Tier eligible for 750 hours per month for one year. If your Free Tier window has expired, compute charges will apply while the instance runs.
GuardDuty has a 30-day free trial. After 30 days, charges apply based on event volume. The CloudTrail S3 bucket will accumulate minimal storage charges (pennies per month).
Resources you used:
- VPC (security-workshop-vpc) with subnets, route tables, and an internet gateway. No ongoing cost.
- EC2 instance (secure-internal-server). Free Tier covers 750 hours/month. Charges apply if you exceed Free Tier limits.
- Security Group (internal-only-sg). No ongoing cost.
- CloudTrail trail (security-workshop-trail). First trail is always free. The S3 bucket storing logs accumulates minimal storage charges.
- GuardDuty. 30-day free trial. After 30 days, charges apply.
- S3 bucket (security-workshop-data-ACCOUNTID). Minimal storage cost for a test file.
- CloudTrail log bucket (aws-cloudtrail-logs-ACCOUNTID-randomstring). Minimal storage cost.
- IAM policy (SecurityWorkshopS3ReadOnly) and role (SecurityWorkshopEC2Role). No cost.
macOS
No action needed. Choose this if you are still actively building or want to explore the security configuration further.
- Monitor your billing dashboard periodically to confirm you remain within Free Tier limits.
- GuardDuty will continue monitoring your account for the remainder of the 30-day trial at no cost.
- The EC2 instance, VPC, and S3 buckets remain intact and available for further experimentation.
Windows
Shut down running compute to free up Free Tier hours while keeping all configuration intact.
- Navigate to the EC2 Console.
- Select the secure-internal-server instance.
- Choose Instance state, then Stop instance.
- Confirm by choosing Stop.
- Your VPC, security groups, IAM resources, CloudTrail trail, GuardDuty, and S3 buckets all remain configured and ready for when you return.
Linux
Remove all project resources completely. Follow these steps in order to avoid dependency errors.
Terminate the EC2 instance:
- Navigate to the EC2 Console.
- Select secure-internal-server.
- Choose Instance state, then Terminate instance.
- Confirm termination. Wait for the instance state to show Terminated.
Delete the S3 buckets:
- Navigate to the S3 Console.
- Select the security-workshop-data-ACCOUNTID bucket.
- Choose Empty, type permanently delete to confirm, and choose Empty.
- After emptying, select the bucket again, choose Delete, type the bucket name to confirm, and choose Delete bucket.
- Repeat the empty-then-delete steps for the CloudTrail log bucket (aws-cloudtrail-logs-ACCOUNTID-randomstring).
Delete the CloudTrail trail:
- Navigate to the CloudTrail Console.
- In the left navigation, choose Trails.
- Select security-workshop-trail and choose Delete.
- Confirm the deletion.
Disable GuardDuty:
- Navigate to the GuardDuty Console.
- In the left navigation, choose Settings.
- In the Suspend GuardDuty section, choose Disable GuardDuty.
- Choose Confirm to disable the service.
Delete the VPC (this removes subnets, route tables, and the internet gateway):
- Navigate to the VPC Console.
- In the left navigation, choose Your VPCs.
- Select security-workshop-vpc and choose Actions, then Delete VPC.
- The confirmation page lists associated resources (subnets, route tables, internet gateway) that will also be deleted.
- Type delete and choose Delete.
Delete the IAM role and policy:
- Navigate to the IAM Console.
- In the left navigation, choose Roles.
- Search for SecurityWorkshopEC2Role, select it, and choose Delete.
- Type the role name to confirm and choose Delete.
- In the left navigation, choose Policies.
- Search for SecurityWorkshopS3ReadOnly, select it, and choose Actions, then Delete.
- Type the policy name to confirm and choose Delete.
Nice Work!
Nice Work!
You just built a hardened AWS environment with four layers of security working together. From network isolation to encryption, your account now demonstrates the same defense-in-depth approach used in production cloud environments.
You've learned how to:
- Lock down an EC2 instance inside a private subnet with no public IP and an empty-inbound Security Group, proving network isolation blocks all internet access.
- Create a least-privilege IAM policy scoped to only s3:GetObject and s3:ListBucket on a specific resource pattern, and attach it to a role that only EC2 can assume.
- Enable CloudTrail and GuardDuty for real-time security monitoring, and protect stored data with SSE-KMS encryption and Block Public Access that actively denies attempts to expose objects.
- Secret Mission: Generated sample GuardDuty findings and practiced interpreting threat alerts to identify affected resources and recommended remediation steps.
Ready to quiz yourself?