--- tags: comp4635(2025) --- # COMP 4635 - W3 Lab 1: Creating Amazon EC2 Instances ## Code of Ethics :::danger * The lab exercises for the course should be attempted ONLY INSIDE THE SECLUDED LAB ENVIRONMENT documented or provided. Please note that most of the attacks described in the lab sheet would be ILLEGAL if attempted on machines that you do not have explicit permission to test and attack. The university, course lecturer, lab instructors and teaching assistants assume no responsibility for any actions performed outside the secluded lab. * The lab network should be regarded as a hostile environment. No sensitive information should be stored on your virtual machine that someone is able to gain access to it. * Do not intentionally disrupt other students who are working in the labs or hack into other student's physical or virtual machines. ::: ## Method of Submission In the following lab, each checkpoint will require you to submit some files **with designated names**. Put all files into a folder and compress them into a ZIP archive named `w3lab1-<your-id>.zip`, where `<your-id>` should be replaced with your student ID. Submit the ZIP archive [on Canvas](https://canvas.ust.hk/courses/63913/assignments/385093). There are in total **6** checkpoints. The base mark is **12** points. ## Accessing the AWS Management Console 1. At the top of [the lab's Canvas page](https://awsacademy.instructure.com/courses/124953/modules/items/11835840) (login if necessary), click **Start Lab** to launch your lab. A Start Lab panel opens displaying the lab status. 2. Wait until you see the message "**Lab status: ready**", then click the **X** to close the Start Lab panel. 3. At the top of the lab page, click **AWS**. This will open the AWS Management Console in a new browser tab. The system will automatically log you in. **Tip**: If a new browser tab does not open, there will typically be a banner or icon at the top of your browser indicating that your browser is preventing the site from opening pop-up windows. Click on the banner or icon and choose "Allow pop-ups." 4. Arrange the AWS Management Console tab so that it displays alongside these instructions. Ideally, you will be able to see both browser tabs at the same time, to make it easier to follow the lab steps. ⚠ **Do not change the Region unless instructed to do so**. 5. The README provided in the lab's Canvas page may look similar, but submission details only exist in this one, and there may be changes that could affect your grading. Therefore, please refer to this lab sheet. 6. In the lab environments, access to AWS services and service actions might be restricted to the ones that are needed to complete the lab instructions. You might encounter errors if you attempt to access other services or perform actions beyond the ones that are described in the task. ## Objectives Traditional methods of deploying servers and configuring security are complex and often involve multiple teams and long delays. Fortunately, it is quick and easy to deploy secure infrastructure in the cloud. As a Systems Operator, you can automate many of these processes using the AWS Command-Line Interface. After completing this lab, you should be able to do the following: - Launch an Amazon EC2 instance using the management console - Launch an Amazon EC2 instance using the AWS Command-Line Interface (AWS CLI) The final architecture will be: ![architecture](https://hackmd.io/_uploads/ryz3m8CXle.png) We will also have a **Challenge section** where you have to troubleshoot some issues with Amazon EC2 instances. ## Task 1 - Launch an Amazon EC2 Instance using the Management Console ### Step 1: Start creating the instance and assign a name In this task, you will launch an Amazon EC2 instance using the management console. The instance will be a Bastion Server, from which you can use the AWS Command-Line Interface (AWS CLI). 1. Choose the **Services** menu, locate the **Compute** services, and select **EC2**. 2. Choose the **Launch instance** button in the middle of the page, and then select **Launch instance** from the dropdown menu. 3. Name the instance: - Give it the name `Bastion Server` *Tags* allow you to categorize your AWS resources in different ways, such as by purpose, owner, or environment. This is useful when you have many resources of the same type &mdash; you can quickly identify a specific resource by their tags. Each tag consists of a _Key_ and a _Value_, both of which you define. **Note**: *Name* is simply another tag. The *key* for this tag is `Name`, and the *value* is `Web Server 1`. This name will appear on the instance in the EC2 management console. ### Step 2: Application and OS Images This step allows you to choose an AMI, which contains a copy of the disk volume that will be used to launch the instance. 🗨 Examine the list of AMIs that are displayed, showing many versions of Microsoft Windows and Linux. These disk images are regularly updated to incorporate security patches and software that helps you use AWS services. You can also create your own AMI that includes your own data and applications, or you can select pre-built commercial applications from the **AWS Marketplace**. 4. Choose an AMI from which to create the instance: - In the list of available *Quick Start* AMIs, keep the default **Amazon Linux** AMI selected. - Also keep the default **Amazon Linux 2023 AMI (HVM)** selected. &nbsp; ### Step 3: Choose an Instance Type This step allows you to choose an **Instance Type**, which determines the resources that will be allocated to your EC2 instance. Each Instance Type allocates a combination of virtual CPUs, memory, disk storage and network performance. Instance Types are divided into **families** such as Compute-optimized, Memory-optimized and Storage-Optimized. The name of the Instance Type includes a family identifier, such as **t2** and **m4**. The number indicates the _generation_ of the instance, so **m5** is newer than **m4**. ![final_instance_ex](https://hackmd.io/_uploads/BkfvZp4rge.jpg) 5. Specify an Instance type: - In the *Instance type* panel, select **`t2.micro`**. This instance type has 1 virtual central processing unit (CPU) and 1 GiB of memory. It is an instance that can burst above baseline performance when it is busy. It is ideal for development, testing and for applications that have bursty workloads. ### Step 4: Choose a key pair 6. Select the key pair to associate with the instance: - From the **Key pair name** menu, select **`vockey`**. The **`vockey`** key pair you selected will allow you to connect to this instance via SSH after it has launched. &nbsp; ### Step 5: Network settings You will launch the instance in a public subnet within the _Lab VPC_ network. 7. Next to Network settings, choose **Edit**. 8. For **VPC**, choose the **Lab VPC**. 9. For **Subnet** accept the Public Subnet. 10. Keep the **Auto-assign public IP** setting set to **Enable**. 11. Under *Firewall (security groups)*, keep the default **Create security group** option chosen. You will create a new Security Group that permits SSH connections. This security group will allow you to log in to the Bastion Server via SSH. 12. Configure the security group: - **Security group name:** `Bastion security group` - **Description:** `Permit SSH connections` - Permissions to allow inbound access via SSH (port 22) have already been configured by default. Keep these settings. &nbsp; ### Step 6: Configure storage This step can be used to add additional Amazon Elastic Block Store (EBS) disk volumes and configure their size and performance. You can click the "info" button to view a description of each field. 13. In the *Configure storage* section, keep the default settings. ### Step 7: Advanced details 14. Expand the **Advanced details** panel and for **IAM instance profile**, choose **Bastion-Role** The _Bastion-Role_ grants permission to applications running on the instance to make requests to the Amazon EC2 service. This is required for the second half of this lab, where you will use the AWS CLI to communicate with the EC2 service. ### Step 8: Launch the instance 15. At the bottom of the **Summary** panel on the right side of the screen choose <span style="background-color:#ec7211; font-weight:bold; font-size:90%; color:white; padding:3px 10px; white-space: nowrap;">Launch instance</span> You will see a Success message. 16. Choose <span style="background-color:#ec7211; font-weight:bold; font-size:90%; color:white; padding:3px 10px; white-space: nowrap;">View all instances</span> The **Bastion Server** instance will first appear in the *Pending* state, which means it is being launched. The state will then change to *Running*, which indicates that the instance has started booting. It takes a few minutes for the instance to boot. 17. Select the **Bastion Server** instance, and review the information in the **Details** tab that displays in the lower pane. Notice that the instance has a **Public IPv4 address**. You can use this IP address to communicate with the instance from the internet. 18. Before you continue, wait for your instance to display the following: - **Instance state:** *Running* - **Status check:** *2/2 checks passed* 🗨 This may take a few minutes. Choose the refresh ⟳ icon at the top of the page every 30 seconds or so to more quickly become aware of the latest status of the instance. :::success ### Checkpoint 1 (2 marks) Submit a screenshot, named **`cp1.{png/jpg/jpeg}`**, showing the created instance and its details. You can do so by simply checking the box next to the instance's name. Make sure the screenshot shows the following: - The instance's name - The instance is in running state - The instance has passed the status checks - The instance's public IPv4 address - The instance's VPC ID ::: ## Task 2: Log into the Bastion Server In this task, you will log into the Bastion Server that you just created. 19. Copy the **IPv4 Public IP** (shown in the lower half of the page) to your clipboard. 🗨 It might take a minute until the _IPv4 Public IP_ value is displayed. 20. Do the following. - Choose the <span style="background-color: #F2F3F4; font-weight: normal; font-size: 90%; color: black; border-radius: 3px; border: 1px solid gray; padding: 5px 6px; white-space: nowrap;">Details</span> drop down menu near the top of the lab's Canvas page, then choose <span style="background-color: #F2F3F4; font-weight: normal; font-size: 90%; color: black; border-radius: 3px; border: 1px solid gray; padding: 5px 6px; white-space: nowrap;">Show</span>. A Credentials window will open. - Choose the **Download PEM** button and save the **labsuser.pem** file. - Then exit the Details panel by choosing the **X**. :::spoiler For Linux / MacOS user 21. Open a terminal window, and change directory `cd` to the directory where the `labsuser.pem` file was downloaded. For example, run this command, if it was saved to your `Downloads` directory: ```bash cd ~/Downloads ``` 22. Change the permissions on the key to be read only, by running this command: ```bash chmod 400 labsuser.pem ``` 23. Return to the terminal window and run this command (replace **<public-ip\>** with the **Public IPv4** value you copied to your clipboard earlier in the lab): ```bash ssh -i labsuser.pem ec2-user@<public-ip> ``` 24. Type `yes` when prompted to allow a first connection to this remote SSH server. Because you are using a key pair for authentication, you will not be prompted for a password. ::: :::spoiler For Windows user 21. If you are using the latest version of Windows 10 or Windows 11, it should include a built-in SSH server and client that are based on OpenSSH. If SSH is not pre-installed in your Windows machine, visit this link and follow the same process as installing SSH on "Windows Server 2022" in your Windows 10/11 machine: https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=powershell&pivots=windows-server-2022 22. Open a Powershell window, and change directory `cd` to the directory where the `labsuser.pem` file was downloaded. For example, run this command, if it was saved to your `Downloads` directory: ```bash cd .\Downloads ``` 23. Run this command (replace **<public-ip\>** with the **Public IPv4** value you copied to your clipboard earlier in the lab): ```bash ssh -i .\labsuser.pem ec2-user@<public-ip> ``` 24. Type `yes` when prompted to allow a first connection to this remote SSH server. Because you are using a key pair for authentication, you will not be prompted for a password. ::: Now that you are connected to the Bastion Server, you can use the AWS CLI to call AWS services. :::success ### Checkpoint 2 (2 marks) Submit a screenshot, named **`cp2.{png/jpg/jpeg}`**, showing the output after connecting to the Bastion Server. The screenshot should be of a terminal. Make sure the screenshot includes the following: - Your `ssh` command, including the IPv4 address used. - The output after your `ssh` command. ::: ## Task 3: Launch an Instance using the AWS CLI In this task, you will launch an Amazon EC2 instance using the AWS Command-Line Interface (CLI). The AWS CLI makes it easy to automate the provision and configuration of AWS resources. The new instance will be configured as a Web Server. ### Obtain the AMI to Use One of the parameters required when launching an instance is the Amazon Machine Image (AMI), which will populate the boot disk of the instance. AMIs are continually patched and updated by AWS, so it is recommended to always use the latest AMI when launching instances. You will use the **AWS Systems Manager Parameter Store** to obtain the ID of the most recent _Amazon Linux 2023_ AMI. AWS maintains a list of standard AMIs in the Parameter Store, making this task easy to automate. 25. Paste this script into your `ssh` session: ```bash # Get token TOKEN=$(curl --request PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600") # Set the Region AZ=$(curl --write-out "\n" --request GET "http://169.254.169.254/latest/meta-data/placement/availability-zone" --header "X-aws-ec2-metadata-token: $TOKEN") export AWS_DEFAULT_REGION=${AZ::-1} # Obtain latest Linux AMI AMI=$(aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 --query 'Parameters[0].[Value]' --output text) echo $AMI ``` This command did the following: - Generated a token that can be used by the Instance Metadata Service v2 (IMDSv2) - Obtained the Region where the instance is running - Called the AWS Systems Manager (_ssm_) and used the **get-parameters** command to retrieve a value from the Parameter Store - The AMI requested was for Amazon Linux 2023 (_al2023-ami_) - The AMI ID has been stored in an Environment Variable called _AMI_ ⚠ If your SSH session disconnects, it will lose the information stored in environment variables. Once you reconnect, you will need to re-run all of the steps in this task, starting with the above commands to obtain the AMI ID. ### Obtain the Subnet to Use You will be launching the new instance in the Public Subnet. When launching an instance, the **SubnetId** can be specified. The following command will retrieve the _SubnetId_ for the Public Subnet: 26. Paste this command: ```bash SUBNET=$(aws ec2 describe-subnets --filters 'Name=tag:Name,Values=Public Subnet' --query 'Subnets[].SubnetId' --output text) echo $SUBNET ``` This uses the AWS CLI to retrieve the Subnet ID of the subnet named _Public Subnet_. &nbsp; ### Obtain the Security Group to Use A _Web Security Group_ has been provided as part of this lab, which allows inbound HTTP requests. 27. Paste this command: ```bash SG=$(aws ec2 describe-security-groups --filters 'Name=group-name,Values=WebSecurityGroup' --query 'SecurityGroups[].GroupId' --output text) echo $SG ``` The command retrieves the _Security Group ID_ of the Web Security Group. ### Download a User Data script You will be launching an instance that will act as a Web Server. To install and configure the web server, you will provide a **User Data script** that will be automatically run when the instance launches. 28. Paste this command to download the User Data script: ```bash wget https://aws-tc-largeobjects.s3.amazonaws.com/ILT-TF-200-ACSOPS-1/lab-2-ec2-linux/UserData.txt ``` 29. Paste this command to view the contents of the script: ```bash cat UserData.txt ``` The script does the following: - Installs a web server - Downloads a zip file containing the web application - Installs the web application ### Launch the Instance You now have all the necessary information require to launch the Web Server instance! 30. Paste this command: ```bash INSTANCE=$(\ aws ec2 run-instances \ --image-id $AMI \ --subnet-id $SUBNET \ --security-group-ids $SG \ --user-data file:///home/ec2-user/UserData.txt \ --instance-type t2.micro \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=Web Server}]' \ --query 'Instances[*].InstanceId' \ --output text \ ) echo $INSTANCE ``` The command launches a new instance (_run_instances_) using these parameters: - **Image:** Uses the AMI value obtained earlier from the Parameter Store - **Subnet:** Specifies the _Public Subnet_ obtained earlier and, by association, the VPC in which to launch the instance - **Security Group:** Uses the _Web Security Group_ obtained earlier, which permits HTTP access - **User Data:** References the User Data script you downloaded, which installs the web application - **Instance Type:** Specifies the type of instance to launch - **Tags:** Assigns a _Name_ tag with the value of _Web Server_ The **query** parameter specifies that the command should return the _Instance ID_ once the instance is launched. The **output** parameter specifies that the output of the command should be in _text_. Other output options are _json_ and _table_. The ID of the new instance has been stored in the _INSTANCE_ environment variable. ### Wait for the Instance to be Ready You can monitor the status of the instance via the Management Console, but you can also query the status via the AWS CLI. 31. Paste this command: ```bash aws ec2 describe-instances --instance-ids $INSTANCE ``` All information related to the instance will be displayed in JSON format. Amongst this information is the instance status. Specific information can be obtained by using the **query** parameter. 32. Paste this command: ```bash aws ec2 describe-instances --instance-ids $INSTANCE --query 'Reservations[].Instances[].State.Name' --output text ``` This is the same command but, rather than displaying all information about the instance, only displays the name of the instance _State_. This will display a status of **pending** or **running**. Repeat the above command until it returns a status of **running**. ### Test the Web Server You can now test that the web server is working. You can retrieve a URL to the instance via the AWS CLI. 33. Paste this command: ```bash aws ec2 describe-instances --instance-ids $INSTANCE --query Reservations[].Instances[].PublicDnsName --output text ``` This returns the **DNS Name** of the instance. 34. Copy the DNS name that is displayed. It should look similar to: _ec2-35-11-22-33.compute-1.amazonaws.com_ 35. Paste the DNS name into a new web browser tab, then press Enter. A web page should be displayed, demonstrating that the web server was successfully launched and configured. You can also see the instance in the EC2 management console. :::success ### Checkpoint 3 (2 marks) Submit a screenshot, named **`cp3.{png/jpg/jpeg}`**, showing the webpage and the connected DNS name. Make sure the screenshot includes the following: - The DNS name used at the address bar of the browser - The webpage in its entirety ::: 36. Return to the web browser tab containing the EC2 management console. 37. In the **Instances** page, choose <i class="fas fa-sync"></i> Refresh. The list should now include the _Web Server_ instance that was launched via the AWS CLI command. As seen in this task, the AWS CLI makes it possible to programmatically access and control AWS services. These commands can be placed in a script and run as a standard process to deploy consistent, reliable infrastructure with minimal scope for human error. **Which method should you use?** - **Launch from the management console** when you quickly need to launch a one-off or temporary instance. - **Launch via a script** when you need to automate the creation of an instance in a repeatable, reliable manner. - **Launch via CloudFormation** when you wish to launch related resources together. :::success ### Checkpoint 4 (2 marks) Submit a screenshot, named **`cp4.{png/jpg/jpeg}`**, showing the new instance and its details. Similar to checkpoint 1, you can do so by simply checking the box next to the instance's name. Make sure the screenshot shows the following: - The instance's name - The instance is in running state - The instance has passed the status checks - The instance's public IPv4 address - The instance's public DNS - The instance's VPC ID ::: ## Challenge 1: Connect to an Amazon EC2 Instance 🗨 _We will not explain the answer during the lecture time. And require you to work on it based on what we have learned._ In this challenge, your mission is to troubleshoot an instance called _Misconfigured Web Server_: 38. Your tasks are: - Obtain the DNS name of the **Misconfigured Web Server** - Try to establish an **SSH connection** to the instance - Diagnose why this does not work and **fix the misconfiguration** :::success ### Checkpoint 5 (2 marks) Submit a TXT or an MD file, named **`cp5.{txt/md}`**, with answers to the following questions: 1. What was the problem? 2. What did you do the fix the problem? Also, submit a screenshot, named **`cp5.{png/jpg/jpeg}`**, showing the output after connecting to the Misconfigured Web Server. The screenshot should be of a terminal, similar to **checkpoint 2**. Make sure the screenshot includes the following: - Your `ssh` command, including the IPv4 address used. - The output after your `ssh` command. ::: ## Challenge 2: Fix the Web Server Installation 🗨 _We will not explain the answer during the lecture time. And require you to work on it based on what we have learned._ In this challenge, your mission is to troubleshoot the the web server installation on the _Misconfigured Web Server_: 39. Your tasks are: - Point your web browser to the public IP address of the _Misconfigured Web Server_ - Why does the web site not appear? - Diagnose the problem and try to fix it on the instance, or use **Launch More Like This** to launch another instance with a fixed configuration :::success ### Checkpoint 6 (2 marks) Submit a TXT or an MD file, named **`cp6.{txt/md}`**, with answers to the following questions: 1. What was the problem? 2. What did you do the fix the problem? Also, submit a screenshot, named **`cp6.{png/jpg/jpeg}`**, showing the webpage and the connected DNS name, similar to **checkpoint 3**. Make sure the screenshot includes the following: - The DNS name used at the address bar of the browser - The webpage in its entirety You should get a screenshot similar to this after fixing the problem. ![image](https://hackmd.io/_uploads/rkl6SR4rxx.png) ::: ## Lab Complete Congratulations! You have completed the lab. Remember to submit the necessary files [on Canvas](https://canvas.ust.hk/courses/63913/assignments/385093)! 40. Choose <span style="background-color: #F2F3F4; font-weight: normal; font-size: 90%; color: black; border-radius: 3px; border: 1px solid gray; padding: 5px 6px; white-space: nowrap;">End Lab</span> at the top of this page and then choose <span style="background-color: #257ACF; font-weight: bold; font-size: 90%; color: white; border-radius: 5px; padding: 3px 10px; white-space: nowrap;">Yes</span> to confirm that you want to end the lab. A panel will appear, indicating that "DELETE has been initiated... You may close this message box now." 41. Choose the **X** in the top right corner to close the panel.