Secure Packages with CodeArtifact

Project 3 of the 6 Day DevOps Challenge - Learn how to set up and use AWS CodeArtifact to manage and secure Java dependencies for your applications.

Introduction

⚡️ 30 second Summary

Welcome to Day THREE of the 6 Day DevOps Challenge!

Today, we're working with AWS CodeArtifact to secure your web app's packages.

Why am I learning about AWS CodeArtifact?

When building apps, you don't create everything from scratch. Instead, you often use pre-made "packages" (chunks of code) that other developers have already created. It's just like making pasta with pre-made pasta sauce, instead of making everything from scratch.

CodeArtifact is an artifact repository, which means you use it to store all of your app's packages in one place. It's an important part of a CI/CD pipeline because it makes sure an engineering team is always using the same, verified versions of packages when building and deploying the app, which reduces errors and security risks!

Get ready to:

  • 🗂️ Set up CodeArtifact as a repository for your project's dependencies.
  • 🛡️ Use IAM roles and policies to give your web app access to CodeArtifact.
  • ✅ Verify your web app's connection to CodeArtifact!
  • 💎 Become a package uploader - create and add your own packages to your CodeArtifact repository!

Wait, what's the 6 Day DevOps Challenge?

Ooooo, glad you asked 😸

In the 6 Day DevOps Challenge, you'll build from scratch a CI/CD pipeline that automates the build and deployment of a web app. This is a 100% hands-on challenge, so get ready to write documentation and add your work to your portfolio along the way (we'll show you how).

Want a complete demo of how to do this project, from start to finish? Check out our 🎬 walkthrough with Natasha 🎬

If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project.

This project is part of a series:

  1. Part 1: Set Up a Web App in the Cloud
  2. Part 2: Connect a GitHub Repo with AWS
  3. Part 3: You are here!
  4. Part 4: Package an App with CodeBuild
  5. Part 5: Deploy an App with CodeDeploy
  6. Part 6: CI/CD with CodePipeline

Before we start Step #1...

Today's project is split into three parts.

PART 1: Web App Setup (i.e. what we did in Project #1 of this challenge)

PART 2: Repository Setup (i.e. what we did in Project #2 of this challenge)

  • In 💻 Step #3, we'll connect your web app's code to a GitHub repository.

PART 3: CodeArtifact Setup

  • In 🗂️ Step #4, we'll create a CodeArtifact repository.
  • In 🛡️ Steps #5 and #6, we're setting up your EC2 instance's permissions to access the CodeArtifact repository.
  • In ✅ Step #7, we'll see the CodeArtifact repository store your web app's packages!

Note

If you've done projects #1 and #2 of the 6 Day DevOps Challenge, the first two parts will be much faster for you - we'll be reusing your existing setup from those projects!

Launch your EC2 Instance

Let's kick things off by launching an EC2 instance! This instance will be our virtual server in the cloud where we'll develop our Java web app.

This is important because Amazon EC2 provides the compute resources we need to host our application and build our CI/CD pipeline.

In this step, you're going to:

  • Launch a new EC2 instance.

Launch an EC2 instance

First things first - have you already done

of the 6 Day DevOps Challenge?

Yes - I've deleted my resources

Woooooo, it's good to see you again! If you've done the first two projects, we'll assume that you...

  • Already have an IAM Admin User.
  • Have VS Code installed.
  • Have a GitHub repo (called nextwork-web-project) with your Java web app code inside.

Setting up your web app environment again is going to be awesome - let's go!

Launch an EC2 Instance

Since we want your web app to be entirely created and run on the cloud, we'll use a virtual server (EC2 instance) to house our development work.

Let's get an EC2 instance up and running!

Tip: We recommend using the following regions

Did you know that not all regions have the same number of AWS services available?

There are only 13 AWS Regions that provide ALL the services we'll use in the 6 Day DevOps Challenge. We'd recommend using one of these regions from the very start of the challenge, so all your resources are in the same place. Even if you don't live in these regions, you can still use them:

  • us-east-1 (N.Virginia)
  • us-east-2 (Ohio)
  • us-west-2 (Oregon)
  • eu-west-1 (Ireland)
  • eu-west-2 (London)
  • eu-central-1 (Frankfurt)
  • eu-north-1 (Stockholm)
  • eu-south-1 (Milan)
  • eu-west-3 (Paris)
  • ap-southeast-1 (Singapore)
  • ap-southeast-2 (Sydney)
  • ap-northeast-1 (Tokyo)
  • ap-south-1 (Mumbai)
  • In your EC2 console, select Instances from the left hand navigation panel.
  • Choose Launch instances.
  • Set up your EC2 instance:
  • In Name, enter the value:
nextwork-devops-[[YOURNAME="enter your name"]]
  • Don't forget to enter your name!
  • Choose Amazon Linux 2023 AMI under Amazon Machine Image(AMI).
  • Leave t2.micro under Instance type.
  • Under Key pair (login), select Create a new key pair and use nextwork-keypair as your key pair's name.
  • If you happened to have saved your key pair from the previous project, check: is your private key (nextwork-keypair.pem) still in your local computer? If you can still find it, you can use the existing newtwork-keypair key pair instead of creating a new one.
  • Store nextwork-keypair.pem in a new folder called DevOps in your local computer's Desktop.
  • Back to our EC2 instance setup, head to the Network settings section.
  • For Allow SSH traffic from, select the dropdown and choose My IP. This makes sure only you can access your EC2 instance. You can double check your IP by clicking here.
  • Choose Launch instance.

Didn't see a success message?

Share any errors/questions with the NextWork community!

Yes - I've kept all my resources

Amazing! If you've kept all your resources, there's no more web app or GitHub set up left to do: straight to CodeArtifact you go 🔥

⬇️ Click here to head straight to CodeArtifact setup.

Nope

Note

You can still complete this project without doing Project 1 (Set Up a Web App in the Cloud) first - but we highly recommend giving it a go and writing documentation on your web app set up too!

If you get stuck in this step, make sure to check out Project 1's step by step guide for in-depth explanations and troubleshooting guidance.

Set up an IAM Admin User

  • Do you have an IAM user?

No

Oooo it's the start of a new era!

If you don't have an IAM user yet - here are the steps to create one (this takes less than 10 mins).

What is an IAM user? Why are we setting one up?

In AWS, a user is a person or a computer that can do things on the AWS cloud.

When you create an AWS account for the first time, the login you get is called the root user of the AWS account. AWS actually recommends to not use your root user for everyday tasks to protect it from security breaches.

You should create IAM users instead. If a root user is a master key to your AWS account, think of IAM users as key copies. IAM users have separate usernames and passwords to your root user, and you can set them to have limited access to your account's resources.

  • Head to your AWS Account as the root user.
  • Open the AWS IAM console.
  • From the left hand navigation panel, choose Users.
  • Choose Create user.
  • For the User name, name it:
[[YOURNAME="enter your name"]]-IAM-Admin
  • Make sure to select the checkbox next to Provide user access to the AWS Management Console - optional.‍
Note

This does not apply to all accounts, but if you're prompted with a pop up panel that says Are you providing access to a person?, choose I want to create an IAM user.‍

  • For the console password, choose Custom password.
  • Type in a password that you will be able to remember/access in the future.
Top tip

You will use this password for all future projects, so make sure to choose a secure one!

  • Deselect the checkbox for Users must create a new password at next sign-in - Recommended.
  • Choose Next.
  • In the permissions set up page, choose Attach policies directly.
  • From the list of Permissions policies, select AdministratorAccess.
  • Choose Next.
  • Choose Create user.
  • Voilà - you've just created your new user! Stay on this page.
  • Choose Download .csv file.
  • Copy the Console sign-in URL.
  • Now you're ready to start using your IAM user. 🏁
  • Log out of your root user's AWS Account.
  • Paste and go to your copied console sign-in URL.
  • Open your downloaded .csv file containing your user's access instructions.
  • Log in using your IAM user's username and password in the .csv file.
  • Once you're logged in, you're ready to use your IAM user for this project! Make sure to keep the login details safe - you'll need them for the entire 6 Day DevOps Challenge!

Yes

Note

PLEASE make sure you log in to your IAM Admin User instead of the root user - it's truly best practice for account security.

Launch an EC2 Instance

Before we get into the juicy work of building your web app, we need to set up a home for your web app's files.

Since we want your web app to be entirely created and run on the cloud, we'll use a virtual server (EC2 instance) to house our development work.

  • Head to the EC2 console.
  • Once you are in the EC2 Dashboard, select the Instances option in the left-hand menu.
  • Click on the Launch instances button to start creating a new EC2 instance.

What is Amazon EC2?

Think of EC2 as your computer in the cloud! Instead of buying physical servers that sit in your office, EC2 lets you rent virtual computers, called instances that live in AWS's data centers. You can choose exactly how powerful you want these computers to be - how much processing power, memory, and storage you need. You can scale up when you need more power or scale down when you don't, and you only pay for what you use (instead of buying an expensive physical server that you might not use all the time).

Engineers and developers use EC2 to host (i.e. make available to users) their applications, databases, and services. In our case, this EC2 instance will be used to develop our Java web app - deploying it and making it available to users comes after we've developed it!

  • In the Name and tags section, enter the following value in the Name field:
nextwork-devops-[[YOURNAME="enter your name"]]
  • Don't forget to enter your name!
  • In the Application and OS Images (Amazon Machine Image) section, make sure Amazon Linux is selected in the dropdown.
  • Choose Amazon Linux 2023 AMI. Make sure it's marked as Free tier eligible, so you don't get charged!

What is an AMI?

An AMI (Amazon Machine Image) is basically a pre-packed computer setup. Think of it like buying a computer that already has Windows or Mac OS installed, plus maybe some software you'll need. When you launch an EC2 instance, you pick an AMI first to decide what operating system and software your virtual computer will start with.

We're using Amazon Linux 2023 because it's specifically optimized to work great with other AWS services, plus it's free tier eligible (so you won't get charged extra for it)!

  • In the Instance type section, select t2.micro from the dropdown menu.

What is instance type?

If AMIs give you pre-built software and operating systems, instance types cover the 'hardware' components. CPU power, memory size, storage space and more!

So, while the AMI decides what operating system your server runs, the instance type determines how fast and powerful it performs. The t2.micro we're using is the most basic model, but it's free tier eligible and perfect for learning or small applications. If you were building a huge e-commerce site or processing mountains of data, you might choose a larger instance type with more CPU power and memory.

  • Check that t2.micro is marked as Free tier eligible.

Create a key pair

  • In the Key pair (login) section, click on Create new key pair.
  • In the Create key pair popup, enter nextwork-keypair as the Key pair name.
  • Keep Key pair type as RSA.
  • Keep Private key file format as .pem.
  • Click Create key pair.
  • Your browser will automatically download the nextwork-keypair.pem file.
  • Let's keep this key pair somewhere safe and easy to access later on!
  • Create a new folder named DevOps on your Desktop.
  • Move the downloaded .pem file to the DevOps folder.

What is a key pair?

Your key pair is essentially a super-secure digital key to your EC2 instance. Just like you wouldn't want just anyone walking into your house, you don't want unauthorized access to your server. The key pair has two parts: the public key (which AWS keeps) and the private key (the .pem file you downloaded). When you connect to your instance, you'll use this private key to prove it's really you. That's why it's crucial to keep your .pem file safe and secure - if someone gets it, they could potentially access your instance too!

Configure network settings

  • In the Network settings section, ensure that Create new security group is selected.
  • Under Inbound rules, you should see a rule for SSH.

What are Security Groups?

Think of a security group as your EC2 instance's bouncer - it decides who gets in and who doesn't. By opening specific ports, you're telling the bouncer "let people in through these specific doors only." For our web app, we need ports 22 (for SSH so you can connect to your instance), 80 (for HTTP web traffic), and 8080 (for our Java application). The security group checks every request trying to reach your EC2 instance against these rules and only lets through traffic that matches. It's your first line of defense against unwanted visitors to your server!

💡 What is SSH?

SSH (Secure Shell) is a cryptographic network protocol that lets you to securely access and manage servers over an unsecured network. It's commonly used to remotely log in to systems and execute commands.

  • In the Source type dropdown for the SSH rule, select My IP. This will automatically populate your current public IP address.
  • Double check that the IP address under My IP is correct - you can check your IP by clicking here.

What if my IP address is different?

If your IP address is different from what's under My IP, select Custom from the dropdown instead.

  • Make sure the IP address ends with /32.

Why end with /32?

Ending with /32 means that only your specific IP address is allowed to access your instance. This is a great tip for security - you're keeping unauthorized users out!

Launch and verify your EC2 instance

  • Before launching, let's review the Summary section on the right side of the page to make sure your configuration is correct:
  • Instances: 1
  • AMI: Amazon Linux 2023
  • Instance type: t2.micro
  • Security group: New security group
  • Storage: 8 GiB
  • Once you've verified the settings, click on the Launch instance button at the bottom of the page.
  • Whooooooosh! You'll get taken to a page that shows your instance launching.

Did your instance fail to launch?

Don't worry - this happens sometimes! Your instance might not be launching because of permissions issues, hitting AWS service limits, or configuration problems.

Let's solve it together:

  • Check that your IAM user has enough permissions to launch EC2 instances
  • Make sure you haven't hit your EC2 instance limit for this region
  • Double-check your instance configuration (AMI, type, security group)
  • Read the error message in the launch log - AWS usually gives you specific hints about what went wrong

If you're still stuck, ask the NextWork community!

  • Once your instance is ready, you should see a success message at the top of the page.
  • Click on the instance ID link to get taken to your newly launched instance.
  • On the Instances page, you'll see your instance listed. Initially, the instance state will be Pending, and it'll take a few minutes to become Running. No need to wait - we can move on to the next step while the instance is booting up!

Great job! You've launched your EC2 instance.

Set Up Your Web App

Now that your EC2 instance is up and running, let's connect to it and prepare it to build our web app. We'll install the necessary tools like Java and Maven.

This is important because to deploy and run our Java web app, we need to access the EC2 instance and set up the required environment.

In this step, you're going to:

  • Use the terminal to connect to your EC2 instance via SSH.
  • Install Java and Maven on the EC2 instance.
  • Generate a basic Java web app.
  • Connect VS Code to your EC2 instance using the Remote - SSH extension.

Do you have VS Code (or your preferred code editor) installed on your computer?

Yep!

  • Great! Launch VS Code (or your preferred code editor).

No, I need to install VS Code

What is VS Code?

Visual Studio Code (VS Code) is one of the most popular tools for creating and managing coding projects. You'll often hear people call VS Code an IDE (Integrated Development Environment), which means software that helps you write and edit code. It's similar to how Microsoft Word or Google Docs help you write documents!

VS Code also comes with extra tools that we'll use to connect to virtual servers like EC2 instances.

  • Install VS Code by following the installation instructions for your OS e.g. Linux, Mac, Windows.

How can I decide which setting/chip option I should pick?

If you're unsure of which chip/settings option to pick for your device:

  • Mac: Select the Apple icon from the top left hand corner of your computer's menu bar. Select About this Mac, and note whether your Chip says Apple or Intel.
  • Windows: Click the Start button and search for System Information. Note whether your System Type says x64-based or ARM-based PC.
  • Linux: Open a terminal and run uname -m. Note whether the output says x86_64 or aarch64/arm64.
  • Once downloaded, you might need to unzip a zip file to access VS Code.
  • Open VS Code in your local computer (you'll find it in your Downloads folder).
  • If a popup asks you to confirm opening VS Code, select Open.
  • Welcome to VS Code!

Open VS Code

  • Open a new terminal within VS Code by selecting Terminal > New Terminal from the top menu.
  • This will open a command-line interface directly within VS Code.
  • Now back in your Desktop, locate the nextwork-keypair.pem file that you downloaded in the previous step.
  • If you haven't created one yet, create a new folder named DevOps on your Desktop. Make sure the .pem file is in this folder.

Why organize your key pairs?

Keeping your key pair files organized, especially in a dedicated folder like DevOps, makes it easier to find and use them when you need to connect to your EC2 instances. This is particularly helpful as you manage more projects and key pairs.

  • In the VS Code terminal, use the cd command to change the current directory to the DevOps folder on your Desktop.

macOS/Linux

  • Type the following command and press Enter:
cd Desktop/DevOps
  • You can confirm the key pair is inside the DevOps folder by running ls (Mac/Linux) or dir (Windows).

Windows

  • Type the following command and press Enter:
cd Desktop\DevOps
  • You can confirm the key pair is inside the DevOps folder by running the ls command (PowerShell) or dir command (Command Prompt).

Why head to the DevOps folder?

By navigating straight to the directory where your key pair file is located, we're making it easy for us to find and connect to your private key (which is what we'll do in the next step).

Change permissions of the key pair file

  • For security reasons, private key files should have restricted permissions to ensure only you can read the file.

macOS/Linux

  • In the terminal, type the following command and press Enter:
chmod 400 nextwork-keypair.pem

What is chmod 400?

chmod is a command used in Linux and macOS to change file permissions. 400 is a numerical representation of permissions:

  • 4 means read permission for the owner.
  • The first digit 4 applies to the owner of the file.
  • The second digit 0 applies to the group.
  • The third digit 0 applies to others (everyone else).

So, chmod 400 nextwork-keypair.pem sets the permissions of your nextwork-keypair.pem file to read-only for the owner and no permissions for group or others. This is a security best practice for private keys.

Windows

  • In the VS Code terminal, make sure you're using PowerShell, then type the following command and press Enter:
icacls "nextwork-keypair.pem" /reset
icacls "nextwork-keypair.pem" /grant:r "[[USERNAME="enter your username"]]:R"
icacls "nextwork-keypair.pem" /inheritance:r

What is this Windows command doing?

The icacls command is used to modify file permissions in Windows:

  • nextwork-keypair.pem is the target file
  • /inheritance:r removes all inherited permissions
  • /grant:r grants specific permissions (replacing existing ones)
  • "${env:USERNAME}:(R)" grants read-only (R) permission to your current Windows user

This achieves the same security goal as the chmod command on Linux/macOS - ensuring only you can read the private key file, which is essential for SSH security.

  • This removes all permissions from the file and grants only read permissions to your user account.
  • Nice work securing your private key!

Connect to your EC2 instance using SSH

  • In the VS Code terminal (still in the DevOps directory), use the ssh command to connect to your EC2 instance.
  • Make sure to replace <your_public_ipv4_dns> with the Public IPv4 DNS you copied from the EC2 console:
ssh -i nextwork-keypair.pem ec2-user@[[EC2="YOUR PUBLIC IPV4 DNS"]]

I'm getting an error!

Ah, classic! Many students have run into an error at this step, and we'll get you unstuck. Make sure there are no spaces in your folder names (e.g. the DevOps folder cannot be titled Dev Ops).

Still stuck? Share any other errors/questions with the NextWork community!

  • To find the Public IPv4 DNS, head back to the EC2 console in your browser.
  • Select the checkbox next to your running instance (nextwork-devops-yourname).
  • In the Details tab (which is open by default when you select an instance), find the Public IPv4 DNS. This is the address you'll use to connect to your EC2 instance.

What is Public IPv4 DNS?

A Public IPv4 DNS (Domain Name System) is like an address that maps to the public IP address of your EC2 instance, which you'd need to connect to your instance over the internet.

  • Copy the Public IPv4 DNS to your clipboard and paste it here:
 [[EC2="YOUR PUBLIC IPV4 DNS"]]
  • Press Enter to run the command.

What does this command do?

  • ssh: This is the command-line tool for initiating an SSH connection.
  • -i nextwork-keypair.pem: The -i flag says "use this identity file", and references your private key file (nextwork-keypair.pem). SSH will use this key to authenticate your connection.
  • ec2-user: This is the default username for Amazon Linux AMIs. AWS Linux instances will accept SSH connections using the ec2-user username by default.
  • @<your_public_ipv4_dns>: This part tells SSH to connect to the hostname or IP address of the remote server you want to connect to, which is your EC2 instance's Public IPv4 DNS.

Putting that all together, this command tells SSH to connect to your EC2 instance using your private key file and the default username for Amazon Linux AMIs!

  • The first time you connect to a new EC2 instance, SSH will ask you to verify the host's authenticity:
  • Type yes and press Enter to continue connecting.

Why confirm host authenticity?

This security prompt is SSH's way of ensuring you are connecting to the intended server and not being redirected to a malicious server. When you type yes, SSH adds the host's key to your known_hosts file on your local machine. For future connections to the same host, SSH will recognize it and you won't be asked again (unless the host key changes, which could indicate a security issue).

  • If the connection is successful, you'll see a welcome message in your terminal, followed by the command prompt which will look something like: [ec2-user@ip-<private_ip> ~]$.
  • The ec2-user@ part tells us that you are logged in as the ec2-user on your EC2 instance.

Install Maven

What is Apache Maven?

Apache Maven is a tool that helps developers build and organize Java software projects. It's also a package manager, which means it automatically download any external pieces of code your project depends on to work.

We're also using Maven today because it's really useful for kick-starting web projects! It uses something called archetypes, which are like templates, to lay out the foundations for different types of projects e.g. web apps.

We'll use Maven later on to help us set up all the necessary web files to create a web app structure, so we can jump straight into the fun part of developing the web app sooner.

  • Install Apache Maven using the commands below. You can copy and paste all of these lines into the terminal together, no need to run them line by line.
wget https://archive.apache.org/dist/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gz

sudo tar -xzf apache-maven-3.5.2-bin.tar.gz -C /opt

echo "export PATH=/opt/apache-maven-3.5.2/bin:$PATH" >> ~/.bashrc

source ~/.bashrc
  • Once you've pasted these commands, don't forget to press Enter on your keyboard.

Getting a "wget: command not found" error?

No problem! This just means the wget utility isn't installed on your EC2 instance by default. wget is the tool we use to download the Maven archive.

Here's how to fix it:

  • Run this command in your terminal: sudo yum install wget -y
  • After installing wget, try running the Maven installation commands again

What do these commands do?

The first command downloads a setup file that tells your computer where to find Apache Maven. Then, the second command extracts the downloaded package and saves it in a folder called opt. Then, the last two commands save a path to the extracted package, so that you can run Maven commands from any directory after this!

Install Java

What is Java? What is Amazon Correto 8?

Java is a popular programming language used to build different types of applications, from mobile apps to large enterprise systems.

Maven, which we just downloaded, is a tool that NEEDS Java to operate. So if we don't install Java, we won't be able to use Maven to generate/build our web app today.

Amazon Corretto 8 is a version of Java that we're using for this project. It's free, reliable and provided by Amazon.

Woah off it goes! You'll see lots of messages in your terminal, which is your computer's way of telling you that the installation is happening.

  • Run these commands in one go:
sudo dnf install -y java-1.8.0-amazon-corretto-devel

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64

export PATH=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/bin/:$PATH

What do these commands do?

The first command installs Java Amazon Corretto 8. Then, the second command tells your EC2 instance how it can find Java, because it'll need to know Java's location to run Java commands! The last command is a time saver - you're saving Java's location so you can run Java commands from anywhere in your EC2 instance without needing to type out the full location each time.

Woah! What's all this text popping up in the terminal?

The text you see after these commands is the terminal keeping you updated about it's progress with installing Java. It shows the specific packages it's going to install, downloading status, and even verifying that everything was installed.

Verify Maven and Java installations

  • Let's verify that Maven and Java are installed correctly. Run the following command in the terminal:
mvn -v

I don't get a version number

Try running mvn -v in your local terminal as well (i.e. Command Prompt in Windows, or Terminal for Linux/Mac). Are you still missing a version number, or do you see a version number now?

If you don't see a version number in your local environment, try re-installing Maven or ask the NextWork community.

  • This checks the version of Maven installed, which confirms that Maven is installed correctly.
  • Next, to verify that you've installed Java 8 correctly, run this next:
java -version
  • This checks the version of Java installed, which confirms that Java is installed correctly.

Important

If the command above doesn't return openjdk version 1.8 (i.e. Java 8), run the following command that lets you to choose the correct Java version: sudo alternatives --config java

🙋‍♀️ Oops! Got a "java: command not found" error?

This is a common issue! It could mean that Java was installed, but your system doesn't know where to find it yet.

Try these steps:

  • Run the command again: export PATH=$JAVA_HOME/jre/bin/:$PATH
  • Then run: source ~/.bashrc
  • If it still doesn't work, try quitting (run exit in the terminal) and reopening your terminal session (run the ssh command again). Sometimes that's all it takes!

If you're still stuck, ask the NextWork community!

To make it easier to work with our web app files on the EC2 instance, we'll use the VS Code Remote - SSH extension. This will let us edit files directly on the EC2 instance from our local VS Code.

Do you already have the Remote - SSH extension installed? We installed them together in Project #1 of this challenge!

Yup - I have it installed!

  • How good!
  • Select the SSH Open a Remote Window icon in the bottom left hand corner - get ready to connect to your EC2 instance.

Nope - How do I install?

Install Remote - SSH in VS Code

  • In VS Code, head to the Extensions view by clicking on the Extensions icon in the Activity Bar on the side (or press Ctrl+Shift+X or Cmd+Shift+X).
  • In the Extensions marketplace search bar, type Remote - SSH.
  • Find the Remote - SSH extension by Microsoft.
  • Click the Install button to install the extension.

What is VS Code Remote - SSH extension?

The VS Code Remote - SSH extension lets you connect to a remote server, like our EC2 instance, and use VS Code to edit files and folders on that server as if they were local.

This is huge. It means you can edit code, run commands, debug, and use all of VS Code's features while your project files are actually on the remote server. The Remote - SSH extension makes it seamless and efficient to develop in remote environments. We love it 👌

Connect to your EC2 instance using Remote - SSH

  • Once the Remote - SSH extension is installed, you'll see a new icon in the bottom-left corner of VS Code, called "Open a remote window" (it looks like a blue or green plug, depending on the IDE colour theme you're using).
  • Click on this icon.
  • In the dropdown menu that appears, select "Connect to Host...".
  • Then, select "+ Add New SSH Host..." from the options.
  • VS Code will prompt you to Enter SSH Connection Command.
  • Ah, we're back to the SSH command we used to connect to our EC2 instance!

Again?! Why am I running the same command twice?

Aha! The last time we did this in step 2, we connected our local terminal to our EC2 instance. This time, instead of our local terminal, we're connecting VS Code to our EC2 instance.

This let us use VS Code to edit files on our EC2 instance from our local computer.

  • You know the drill...
  • Type the following SSH command into the input box, replacing <your_public_ipv4_dns> with your actual Public IPv4 DNS of your EC2 instance.
ssh -i nextwork-keypair.pem ec2-user@[[EC2="YOUR PUBLIC IPV4 DNS"]]
  • Press Enter after typing the command.

I'm getting an error!

Ah, classic! Many students have run into an error at this step, and we'll get you unstuck. Make sure there are no spaces in your folder names (e.g. the DevOps folder cannot be titled Dev Ops).

Still stuck? Share any other errors/questions with the NextWork community!

  • Select the configuration file at the top of your window. It should look similar to /Users/username/.ssh/config
  • A Host added! popup will confirm that you've set up your SSH Host - yay!
  • Select the blue Open Config button on that popup.
  • Confirm that all the details in your configuration file look correct:
    • Host should match up with your EC2 instance's IPv4 DNS.
    • IdentityFile should match up to nextwork-keypair.pem's location in your local computer.
    • User should say ec2-user
  • Open the Remote SSH Window again, this time selecting the first option to connect to the EC2 instance you added.
  • VS Code will ask if you want to continue connecting to this EC2 instance. Just like your local terminal, this is VS Code's way of asking if you trust this server.
  • Select Continue.

Getting a "Connection refused" error when trying to SSH?

Don't worry - many NextWork students have faced this exact same error! There are a few common reasons this happens.

Let's solve it together:

  • Check your security group settings in the EC2 console - make sure SSH (port 22) traffic is allowed from your IP address
  • If you just launched your instance, it might still be initializing - wait a couple minutes and try again
  • Check that the instance status shows "Running" and "2/2 checks passed" in the EC2 dashboard
  • Try pinging your instance to see if it's reachable (though this isn't always reliable as ICMP might be blocked)
  • As a last resort, try restarting your EC2 instance from the AWS console

If you're still stuck, ask the NextWork community!

Off we gooooooooooo to a new VS Code window ✈️

Create your Java web app

Now that we have Java and Maven installed on our EC2 instance, and an SSH connection via VS Code, let's create a basic Java web app using Maven.

This is important because we need a web app to deploy and test our CI/CD pipeline. Maven will help us quickly set up the project structure.

Note

Before we generate the web app - have you already completed Projects #1 and #2 of the 6 Day DevOps Challenge? If you have, you might recall already setting up a web app and pushing its code into a Git repository...

Yes - I have the web app code in GitHub!

Awesome! Let's make use of that code by cloning what we already have. No need to regenerate the web app from scratch :)

Clone Web App Repository

  • In the EC2 terminal, run the following command, replacing <repository_url> with your GitHub repository's HTTPS URL.
git clone [[REPOURL="<repository_url>"]]
  • Not sure where to find the repository URL?
  • Log in to your GitHub account.
  • Select your profile picture on the top right corner, and select My repositories.
  • Navigate to your GitHub repository for the web application in your web browser.
  • On your GitHub repository page, click on the green Code button.
  • A dropdown menu will appear. Copy the HTTPS URL provided in the dropdown.
  • Paste and run the repository URL in your command.

Getting a "git: command not found" error?

No worries - this just means Git isn't installed on your EC2 instance yet! This is super easy to fix:

  • Run this command to install Git: sudo dnf install git -y
  • After installation completes, verify it worked by running: git --version

Open Project Folder in VS Code

  • In VS Code, click Open Folder in the Explorer panel (top left corner).
  • Select the cloned project folder (nextwork-web-project) in your home directory and click OK.
  • You should now see the files and folders of your web application project in the VS Code Explorer.
  • If VS Code prompts Do you trust the authors of the files in this folder?, click Yes, I trust the authors.
  • Close any popup that you might get about installing another extension.
  • To verify that your web app code is present, open src/main/webapp/index.jsp by double-clicking it and check its content.
  • You can now skip Step #3 and head on over to creating your CodeArtifact repository! See you at Step #4.

Nope - I need to generate this web app from scratch!

Sounds like a plan! Let's generate the web app from scratch together.

  • In your EC2 instance terminal, run the following Maven command to generate a basic Java web app structure. Copy and paste the entire command and press Enter:
mvn archetype:generate \
  -DgroupId=com.nextwork.app \
  -DartifactId=nextwork-web-project \
  -DarchetypeArtifactId=maven-archetype-webapp \
  -DinteractiveMode=false

Break down these commands for me... What is mvn?

When you run mvn commands, you're asking Maven to run a task (like creating a new project or building an existing one).

The mvn archetype:generate command specifically tells Maven to create a new project from a template (which Maven calls an archetype). This command sets up a basic structure for your project, so you don't have to start from scratch.

💡 Extra for Experts: Some of the details you've specified in this command are...

  • -DartifactId=nextwork-web-project names your project
  • -DarchetypeArtifactId=maven-archetype-webapp specifies that you're creating a web application.
  • -DinteractiveMode=false runs the command without pausing for user input, so Maven will go ahead and install everything without waiting for your confirmation. Just like our Java installation, our terminal is now filled up with lots of messages. This is your computer's way of telling you that the application is getting created!
  • After running the command, you should see a BUILD SUCCESS message in your terminal output. This tells us that Maven has successfully generated the web app!
  • You can also verify that a new directory named nextwork-web-project has been created in your home directory (/home/ec2-user/).
  • You can even list the contents of your home directory by running ls (run ls even if you're using a Windows computer, since you're now running commands in your Linux EC2 instance).

Getting an "mvn command not found" error?

This is a common hiccup! It means Maven isn't properly installed or your system can't find it.

Let's fix it together:

  • Double-check that you correctly downloaded and extracted Maven to /opt/apache-maven-3.5.2
  • Make sure your PATH includes Maven by running: echo $PATH - you should see /opt/apache-maven-3.5.2/bin in the output
  • If it's not there, run: echo "export PATH=/opt/apache-maven-3.5.2/bin:$PATH" >> ~/.bashrc followed by source ~/.bashrc
  • Check for any typos in the Maven command itself

If you're still stuck, ask the NextWork community!

Awesome! You've successfully created a Java web app using Maven.

  • You'll see an Open Folder button at the top of the Explorer panel. Click on Open Folder.
  • In the file dialog that appears, head to /home/ec2-user/ directory.
  • Select the nextwork-web-project folder.
  • Select OK.
  • VS Code might show you a popup asking if you trust the authors of the files in this folder. If you see this popup, select Yes, I trust the authors.
  • After opening the folder, VS Code will reload, and you should now see the files and folders of your nextwork-web-project in the Explorer panel.

Connect Your Web App to GitHub

Let's connect our local web app to a remote repository on GitHub. This will let us track changes to our code and collaborate with others!

In this step, you'll:

  • Install Git on your EC2 instance.
  • Set up a GitHub repository.
  • Connect your local web app to the GitHub repository.

Install Git

To start using Git, we need to install it on your EC2 instance.

  • Open a new terminal in VS Code (if you don't already have one open in the remote session) by selecting Terminal > New Terminal. This terminal is now connected to your EC2 instance.
  • Run the following commands in the terminal to update the package list and install Git:
sudo dnf update -y

sudo dnf install git -y

Why install Git on the EC2 instance?

Git is a version control system that we'll use to manage our web app's code. We need to install Git on the EC2 instance so we can initialize a Git repository in our project directory, track changes, and push our code to GitHub in the next steps.

  • Off we goooo! Git is installed - you should see a Complete! message like this:
  • To check that Git was installed correctly, run the following command in the terminal:
git --version
  • This command will show you the installed version of Git if it's installed correctly.

Nice, Git is installed! You're ready to track the changes you make to your web app. We're also going to set up a remote repository on GitHub, so your web app code is also stored in the cloud.

Set up your GitHub repository

  • Do you have a GitHub account?

Yes - I'm ready to go!

No - I need to set up a GitHub account

Oooo exciting let's get you set up 🤘 Signing up is free and takes just 5 minutes!

What is Github?

GitHub is a place for engineers to store and share their code and projects online. It's called GitHub because it uses Git to manage your projects' version history.

  • Follow the prompts to create your account by entering your email, creating a password, and choosing a username.
  • Complete one of their bot verification tasks. Switch the task type to Audio if the Visual task crashes your website.
  • Once your account is created, confirm your email address with a verification code sent to your inbox.
  • Log into your GitHub account once you've verified your email.
  • Welcome to your GitHub account!
  • Click on the "+" icon in the top right corner of the page, next to your profile icon.
  • From the dropdown menu, select "New repository".
  • Nice! We're ready to create a new repository. Fill out the Create a new repository page.
  • In the Repository name field, enter nextwork-web-project
  • In the Description (optional) field, add a description like: Java web app set up on an EC2 instance. This web app was set up as a part of the NextWork's CI/CD Pipeline series.
  • Choose Public for the repository visibility.
  • Leave the Initialize this repository with: options unchecked.
  • Click the Create repository button.

What is GitHub?

GitHub is like a social network for code! It's where developers store their projects, track changes, and collaborate with others. At its heart, GitHub uses Git (a version control system) to keep track of every change made to your code. This means you can see who changed what, when they changed it, and even roll back to previous versions if something breaks.

GitHub is also where many companies look when hiring developers - your GitHub profile is essentially your coding portfolio. For our project, we're using GitHub to safely store our code and track all the changes we make as we build our CI/CD pipeline. Plus, you can keep this repository to show off this project to potential employers later!

  • Go back to VS Code, and open the terminal connected to your EC2 instance.
  • Make sure you're in your web app directory - run pwd and make sure it returns /home/ec2-user/nextwork-web-project.
  • Initialize a new Git repository in this directory by running:
git init

What does git init do?

To start using Git for your project, you need to create a local repository on your computer.

When you run git init inside a directory e.g. nextwork-web-project, it sets up the directory as a local Git repository which means changes are now tracked for version control.

💡 What's a local repository?

The local repository is where you use Git directly on your own EC2 instance. The edits you make in your local repo is only visible to you and isn't shared with anyone else yet

This is different to the GitHub repository, which is the remote/cloud version of your repo that others can see.

WOAH! I got a bunch of yellow text when I ran this command

This yellow text is just Git giving you a heads-up about naming your main branch master and suggesting that you can choose a different name like 'main' or 'development' if you want.

💡 What is a main branch?

You can think of Git branches as parallel versions or 'alternate universes' of the same project. For example, if you wanted to test a change to your code, you can set up a new branch that lets you diverge from the original/main version of your code (called master) so you can experiment with new features or test bug fixes safely. We won't create new branches in this project and we'll save all new changes directly to master, but it's best practice to make all changes in a separate branch and then merge them into master when they're ready.

Add remote origin

Now let's connect your local project folder with your Github repo!

  • Head back to your terminal in VS Code.
  • Add the remote repository as the origin with the following command, replacing <repository_url> with your repository's URL:
git remote add origin [[REPOURL="<repository_url>"]]

What does 'remote add origin' mean?

Your local and GitHub repositories aren't automatically linked, so you'll need to connect the two so that updates made in your local repo can also reflect in your GitHub repo.

When you set remote add origin, you're telling Git where your GitHub repository is located. Think of origin as a bookmark for your GitHub project's URL, so you don't have to type it out every time you want to send your changes there.

  • To find the URL of your GitHub repository, head back to your Git repository page.
  • In the blue section of the page titled Quick setup - if you've done this kind of thing before, copy the HTTPS URL to your repository page. It will look like https://github.com/username/nextwork-web-project.git
  • To verify that the remote origin has been set up correctly, run the command:
git remote -v
  • This command lists all configured remote repositories!
  • You should see origin listed, with both fetch and push URLs pointing to your GitHub repository URL.

Add, commit, and push your code to GitHub

Now, let's add all the files in your project to the Git repository. To do this, there are three commands you need to run...

  • First, run this command in your terminal:
git add . 

What does this command do?

git add . stages all (marked by the '.') files in nextwork-web-project to be saved in the next version of your project.

💡 What does staging mean?

When you stage changes, you're telling Git to put together all your modified files for a final review before you commit them. This is incredibly handy because you get to see all your edits in one spot, which means its much easier to check if there were are mistakes or unwanted changes before you commit.

  • Run this command next in your terminal:
git commit -m "Updated index.jsp with new content"

What does this command do?

git commit -m "Updated index.jsp with new content"saves the staged changes as a snapshot in your project's history. This means your project's version control history has just saved your latest changes in a new version. -m flag lets you leave a message describing what the commit is about, making it easier to review what changed in this version.

  • Finally, run this command:
git push -u origin master

What does this command do?

git push -u origin master uploads i.e. 'pushes' your committed changes to origin, which you've bookmarked as your GitHub repo. 'master' tells Git that these updates should be pushed to the master branch of your GitHub repo. By using -u you're also setting an 'upstream' for your local branch, which means you're telling Git to remember to push to master by default. Next time, you can simply run git push without needing to define origin and master.

  • When you run git push, you might get asked for your GitHub username and password.

Why is Git asking for my username?

Git needs to double check that you have the right to push any changes to the remote origin your local repo is connected with. To do this, Git is now authenticating your identity by asking for your GitHub credentials.

  • Enter your Github username, and press Enter on your keyboard.
  • Next, enter your password. You'll notice that as you type this out, nothing shows on your terminal. This is totally expected - your terminal is hiding your input for your privacy. Press Enter on your keyboard when you've typed out your password, even if you don't see it printed out in your terminal.
  • Hmmmm, now Git is letting us know that it can't actually accept our password.

What does this mean?

GitHub phased out password authentication to connect with repositories over HTTPS - there are too many security risks and passwords can get intercepted over the internet 🤺 You need to use a personal access token instead, which is a more secure method for logging in and interacting with your repos.

💡 What is a token?

A token in GitHub is a unique string of characters that looks like a random password. For example, a GitHub token might look like ghp_xHJNmL16GHSZSV88hjP5bQ24PRTg2s3Xk9ll. As you can imagine, tokens are great for security because they're unique and would be very hard to guess.

Set up and use a GitHub Personal Access Token (PAT)

  • To create a PAT, go back to your GitHub account in your web browser.
  • Click on your profile icon in the top right corner.
  • Select Settings from the dropdown menu.
  • In the left sidebar, scroll down and click on Developer settings.
  • Under Developer settings, click on Personal access tokens.
  • Click on Tokens (classic).
  • Click on Generate new token (classic).
  • Now you're on the New personal access token (classic) page!
  • In the Note field, enter the reason why you're generating this token, like Generated for EC2 Instance Access. This is a part of NextWork's 6 Day DevOps Challenge.
  • For Expiration, you can set it to 7 days for this project, or choose a different duration as per your preference.

What is a token expiration limit?

A token expiration limit means how long your personal access token would work for. After this time period, the token expires and no longer grants access, so you'll need to generate a new token. GitHub does this to make sure any tokens that are left lying around for months or years can't get picked up and used by someone else.

  • Under Select scopes, select the checkbox next to repo.

What do all these scopes mean?

We use scopes to decide what kind of permissions your token will grant. Each scope you pick gives the token the ability to do even more things with your GitHub account. In our case, we picked the repo scope, which means the token can even access and control private repositories in your account.

  • Scroll down and click the Generate token button at the bottom of the page.

Copy and use your Personal Access Token

  • Nice, a new token (a long string of random letters) is generated!
  • Make sure to copy the generated token right away - you won't be able to see it again after you leave this page 🍵
  • Click the Copy to clipboard icon next to your new token to copy it, and paste it somewhere safe now.
  • Go back to your VS Code terminal.
  • Re-run the git push -u origin master command - you can use the up ⬆️ key on your keyboard to re-run a previous command.
  • When asked for your username, enter your GitHub username again.
  • ✋ PAUSE
  • Do you remember what the GitHub token was generated for?
  • When Git asks for your password, paste in your token instead.
  • When you paste, it'll look like nothing is happening. That's because your terminal won't show your token for privacy reasons.
  • Press Enter on your keyboard once you've pasted your token (even if you don't see it on screen).
  • You'll see output in the terminal telling us that the push was successful, such as "Enumerating objects...", "Writing objects...", and "Branch 'master' set up to track remote branch 'master' from 'origin'".

What do these messages mean?

These messages show the progress of transferring objects (like files and commits).

Once the push is done, you also get messages that tell you that your local branch is now tracking the remote branch after the push. This means you only have to run git push next time, instead of the full git push origin master.

  • Well done! Looks like Github recognises your token and pushed your changes to your repository.

Important Secufrity Note

Treat your Personal Access Token like a password. Keep it secure and do not share it with anyone or commit it into your code. If you accidentally share your token, make sure to delete it straight away and generate a new one.

Verify code in GitHub repository

  • To confirm that your code has been successfully pushed to GitHub, let's refresh your GitHub repository page in your browser.
  • You should now see all your web app files listed in your GitHub repository. SO good!

Congratulations! You've successfully connected your web app to GitHub. Your code is now safely stored in a remote repository, and you can track changes and collaborate more effectively.

To avoid having to enter your username and PAT every time you push to GitHub, you can configure Git to store your credentials.

This is optional but can make your workflow smoother!

YES - let's configure Git

  • Run the following command to configure Git to use the store credential helper:
git config --global credential.helper store
  • After running this command, try pushing again: git push. You might be asked for your credentials one last time. Once entered, Git will store them for future pushes.
  • Refresh your GitHub repository page in your browser again.
  • Open the index.jsp file in your repository on GitHub.
  • Verify that the changes you made (<h2>Hello {YOUR_NAME}!</h2> and the new paragraph) are now visible in the file on GitHub.

Nope - skip configuration

  • No problem, onwards and upwards! You can continue without configuring the credential helper.
  • You'll just need to enter your GitHub username and personal access token each time you push changes to GitHub. Make sure to keep the token safe!

Let's GO! Your web app is now fully connected to GitHub, and you're ready for the next steps in setting up your CI/CD pipeline.

Set Up AWS CodeArtifact Repository

Now, let's set up AWS CodeArtifact, a fully managed artifact repository service. We'll use it to store and manage our project's dependencies, ensuring secure and reliable access to Java packages.

This is important because CodeArtifact provides a centralized, secure, and scalable way to manage dependencies for our Java projects, improving build consistency and security.

In this step, you're going to:

  • Create and configure a new CodeArtifact repository.

Create and configure your CodeArtifact repository

  • Head back to the AWS Management Console.
  • Head to the CodeArtifact service.
  • In the CodeArtifact console, in the left-hand menu, click on Repositories.
  • Click the Create repository button to start creating a new repository.

What is AWS CodeArtifact?

CodeArtifact is a secure, central place to store all your software packages. When you're building an application, you typically use dozens of external packages or libraries - things other developers have created that you don't want to build from scratch.

An artifact repository gives you a consistent, reliable place to store and retrieve these components. This gives you three big benefits:

  • 1️⃣ Security: Everyone in a team retrieves packages from a secure repository (CodeArtifact), instead of downloading from unsafe sources on the internet (hello, security risks)!
  • 2️⃣ Reliability: If public package websites go down, you have backups in your CodeArtifact repository.
  • 3️⃣ Control: Your team can easily share and use the same versions of packages, instead of everyone working with a different version of the same package.
  • On the Create repository page, head to the Repository configuration section.
  • In the Repository name field, enter nextwork-devops-cicd.
  • In the Repository description - optional field, enter: This repository stores packages related to a Java web app created as a part of NextWork's CI/CD Pipeline series.
  • Under Public upstream repositories - optional, select the checkbox next to maven-central-store.
  • This will configure Maven Central as an upstream repository for your CodeArtifact repository.

What are upstream repositories?

Upstream repositories are like backup libraries that your primary repository can access when it doesn't have what you need. If you didn't set up CodeArtifact or have an upstream repository, your build would fail because a package is missing!

When your application looks for a package that isn't in your CodeArtifact repository, CodeArtifact will check its upstream repositories (like Maven Central in our case) to find it.

Once found, Maven will then store a copy in your CodeArtifact repository for future use. This gives you three major benefits that you'll appreciate as your projects grow:

  1. Speed - After the first download from Maven Central, retrieving packages directly from CodeArtifact will speed up how quickly your app starts up and runs.
  2. Reliability - If Maven Central goes down (which happens more often than you'd think!), your builds keep working because you've got local copies
  3. Control - You can audit which external packages are being used in your organization and even block problematic ones if needed.

What is Maven Central?

Maven Central is essentially the App Store of the Java world - it's the most popular public repository where developers publish and share Java libraries. When you're building Java applications, chances are you'll need packages from Maven Central. It contains virtually every popular open-source Java library out there, from database connectors to testing frameworks and UI components.

By connecting our CodeArtifact repository to Maven Central, we're setting up a system where we get the best of both worlds: access to all these public libraries, but with the added benefits of caching, control, and consistency that come with our private CodeArtifact repository.

  • Click Next.
  • You're now ready to set up your CodeArtifact domain!

What is a CodeArtifact domain?

A CodeArtifact domain is like a folder that holds multiple repositories belonging to the same project or organization. We like using domains because they give you a single place to manage permissions and security settings that apply to all repositories inside it. This is much more convenient than setting up permissions for each repository separately, especially in large companies where many teams need access to different repositories.

With domains, you can ensure consistent security controls across all your package repositories in an efficient way.

  • Under Domain selection, choose This AWS account.
  • Under Domain name, enter nextwork.
  • Click Next to proceed.
  • Now we're on the last page! Let's Review and create.
  • Review the details of your repository configuration, including the package flow at the top.

What is this package flow diagram?

The package flow diagram shows you exactly how dependencies will travel to your application. When your project needs a dependency, it first looks in your CodeArtifact repository. If the package is already there, great! It uses that version. If not, CodeArtifact automatically reaches out to Maven Central to fetch it.

This is important to understand because it affects how quickly your builds run and how resilient they are to network issues. The first time you request a package, it might take a moment longer as CodeArtifact fetches it from Maven Central. But every build afterwards will be faster because the package is now cached in your repository. It's like the difference between ordering groceries for delivery versus already having them in your fridge!

  • Before you finish reviewing, let's check off a few key details:
  • Repository name: nextwork-devops-cicd
  • Domain name: nextwork
  • Public upstream repository: maven-central-store
  • Select the Create repository button to create your CodeArtifact repository.
  • You'll be taken to the repository's details page.
  • You should see a success message at the top of the page, telling us that the CodeArtifact repository nextwork-devops-cicd has been successfully created.

Great job! You've set up your AWS CodeArtifact repository.

In the next step, we'll start connecting our web app's package manager, Maven, to this repository.

Create an IAM Policy for CodeArtifact Access

For Maven to start working with CodeArtifact, we need to create an IAM role that grants our EC2 instance the permission it needs to access CodeArtifact.

Otherwise, Maven can try all it wants to command your EC2 instance to store and retrieve packages from CodeArtifact, but your EC2 instance simple wouldn't be able to do anything! And going another layer deeper, IAM roles are made of policies; so we need to create policies first before setting up the role.

In this step, you're going to:

  • Try connecting Maven with CodeArtifact (error!)
  • Create a new IAM policy.
  • Set up the policy to grant an EC2 instance access to CodeArtifact.

Get CodeArtifact connection instructions

  • On your newly created repository's page, click the View connection instructions button at the top right corner.
  • In the Connection instructions page, we're configuring how Maven will connect to your CodeArtifact repository.
  • For Operating system, select Mac and Linux.
  • For Package manager client, select mvn (Maven).

How did we know to choose Mac & Linux for operating system, mvn as package manager?

Even if you're doing this project on a Windows computer, don't forget that the EC2 instance we're using was launched with Amazon Linux 2023 as its AMI!

mvn is short for Maven, which is the tool we installed to manage the building process for our Java web app. This also makes Maven our package manager, i.e. the tool that helps us install, update and manage the external packages our web app uses.

  • 🚨 Double check that you're using Mac and Linux as the operating system. Even if you're doing this project on a Windows computer, Mac and Linux is the right choice - your EC2 instance is an Amazon Linux 2023 instance!
  • Make sure that Configuration method is set to Pull from your repository.
  • Nice! The menu will now show you the steps and commands needed to connect Maven to your CodeArtifact repository.

Export CodeArtifact authorization token

  • In the Connection instructions dialog, find Step 3: Export a CodeArtifact authorization token....

What is this step for?

😳 "Export a CodeArtifact authorization token for authorization to your repository from your preferred shell" sounds a little technical!

It actually just means you need to run the command in Step 3 to give your terminal a temporary password. That password will grant your development tools (i.e. Maven) access to your repositories in CodeArtifact.

Maven uses this token whenever it needs to fetch something from your CodeArtifact repository.

  • Copy the entire command in Step 3.
  • Go back to your VS Code terminal, which is connected to your EC2 instance.
  • Paste the copied command into the terminal and press Enter to run it.
  • Uhhh... looks like we got an error!

Why did we get this error?

That Unable to locate credentials error is actually a good security feature in action! Your EC2 instance is essentially saying, "I don't know who you are, so I can't let you access CodeArtifact."

This happens because, by default, your EC2 instance doesn't have permission to access your other AWS services (including CodeArtifact). This is intentional - AWS follows the "principle of least privilege," meaning resources only get the minimum permissions they need to function.

Create a new IAM policy

  • In the AWS Management Console, head to the the IAM console.

What is IAM?

IAM stands for Identity and Access Management. You'll use AWS IAM to manage the access level that other users and services have to your resources.

  • In the IAM console, in the left-hand menu, click on Policies.

What is an IAM policy?

An IAM policy is a set of rules for who can do what with your AWS resources. In AWS, policies determine what actions are allowed or denied for a specific IAM entity (like an EC2 instance)!

  • Click the Create policy button to start creating a new IAM policy.
  • On the Create policy page, select the JSON tab.
  • Replace the default content in the text editor with the following JSON policy document. Copy and paste the entire JSON code block:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codeartifact:GetAuthorizationToken",
                "codeartifact:GetRepositoryEndpoint",
                "codeartifact:ReadFromRepository"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "sts:GetServiceBearerToken",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "sts:AWSServiceName": "codeartifact.amazonaws.com"
                }
            }
        }
    ]
}

What's in this policy?

This JSON document is like a security rulebook. It's written in a specific format that AWS understands, with two main parts:

  1. The first part (codeartifact:* actions) gives permission to get authentication tokens, find repository locations, and read packages from repositories.
  2. The second part (sts:GetServiceBearerToken) allows temporarily elevated access specifically for CodeArtifact operations.

The "Resource": "*" means these permissions apply to all relevant resources, while the Condition narrows the second permission to only work with CodeArtifact.

This follows the "principle of least privilege" - granting only the minimum permissions needed to perform the required tasks, enhancing your security posture.

Would you like to dive deeper into this policy, and explore it line by line? 🔍

No - skip the details

All good - onwards and upwards!

Yes - let's explore the policy line by line

What does this JSON policy document do?

This JSON document defines an IAM policy that grants specific permissions required for accessing AWS

CodeArtifact repositories. Let's break down the policy:

  • Version: "2012-10-17" is the version of the policy language.
  • Statement is a list of statement objects, each defining one or more permissions.

First Statement:

  • "Effect": "Allow" means that this statement grants permission.
  • "Action" lists the actions that are allowed. Here, it includes:
    • "codeartifact:GetAuthorizationToken" allows getting an authorization token for CodeArtifact.
    • "codeartifact:GetRepositoryEndpoint" allows retrieving the endpoint for a CodeArtifact repository.
    • "codeartifact:ReadFromRepository" allows reading packages from a CodeArtifact repository.
  • "Resource": "*" means these actions are allowed on all resources (*) in CodeArtifact. In a production environment, you would typically restrict this to specific resources for better security.

Second Statement:

  • "Effect": "Allow" means this statement grants permission.
  • "Action": "sts:GetServiceBearerToken" allows calling the GetServiceBearerToken action from the AWS Security Token Service (STS).
  • "Resource": "*" means this action is allowed on all resources.
  • "Condition" adds a condition to this permission.
    • "StringEquals" is a condition that checks for string equality.
    • "sts:AWSServiceName": "codeartifact.amazonaws.com": This condition ensures that the sts:GetServiceBearerToken action is only allowed when the AWS service name is codeartifact.amazonaws.com. This is a security measure to restrict the use of this STS action specifically for CodeArtifact.
  • After pasting the JSON policy document, click the Next button at the bottom right.
  • On the Review policy page, in the Policy name field, enter codeartifact-nextwork-consumer-policy.
  • In the Description - optional field, add a description like: Provides permissions to read from CodeArtifact. Created as a part of NextWork CICD Pipeline series.
  • Review the Summary of your policy to ensure the permissions and details are correct.
  • Click the Create policy button to create the IAM policy.

Getting a validation error?

This happens to many students! IAM is quite particular about what characters it allows in policy descriptions.

Here's the quick fix (you can also watch the NextWork team fix this error live.)

  • Review your policy's name and description
  • Remove any special characters, especially apostrophes ('), forward slashes (/), or other non-alphanumeric characters.
  • Make sure to also remove any blank lines at the bottom of your description box.
  • For example, if you wrote "NextWork's" in the description, change it to "NextWork" (without the apostrophe)
  • Try creating the policy again with the simplified text

If you're still stuck, ask the NextWork community!

  • After clicking Create policy, you should see a success message at the top of the IAM Policies page, telling us that the policy codeartifact-nextwork-consumer-policy has been successfully created.

Well done! You've created an IAM policy that will allow EC2 instances to access CodeArtifact. In the next step, we'll attach this policy to an IAM role and then associate that role with your EC2 instance.

Attach IAM Policy and Verify CodeArtifact Connection

Now that we've created the IAM policy for CodeArtifact access, let's attach it to an IAM role and then associate that role with our EC2 instance. This will grant our EC2 instance the permissions it needs to securely access CodeArtifact. Finally, we'll verify the connection to CodeArtifact from our EC2 instance.

This is important because attaching the IAM role to our EC2 instance is what actually grants the instance the permissions defined in the policy, enabling secure access to CodeArtifact.

In this step, you're going to:

  • Create a new IAM role for EC2 that has your new policy attached.
  • Attach the IAM role to your EC2 instance.
  • Re-run the export token command, this time seeing a successful response 🙏

Create a new IAM role for EC2

  • In the IAM console, in the left-hand menu, click on Roles.

What is an IAM role?

An IAM role is like a set of permissions that you can assign to your AWS resources.

For our project, we're creating an IAM role specifically for an EC2 instance to get CodeArtifact access, but roles can grant permissions to any AWS service.

💡 What's the difference between a policy and a role?

Think of a policy as the actual list of permissions - it's a document that specifies exactly what actions are allowed or denied on which AWS resources. For example, "allow reading from this S3 bucket" or "allow publishing to CodeArtifact."

A role is the container that holds these policies and can be assumed by users, applications, or AWS services. You attach policies to roles, then assign the role to whoever needs those permissions.

This separation is powerful because:

  • You can attach the same policy to multiple roles
  • A role can have multiple policies attached
  • You can modify a policy once and affect all roles using it
  • Roles can be assumed temporarily, while policies define the permanent permission boundaries

It's like the difference between writing down rules (policies) and creating a job position (role) that follows those rules. The position can be filled by different people or services, but the rules remain consistent.

  • Click the Create role button to start creating a new IAM role.
  • For Select entity type, choose AWS service.
  • Under Choose a use case, select EC2 from the list of services.
  • Click Next to proceed to the Add permissions step.
  • In the Add permissions step, in the Filter policies search box, type codeartifact-nextwork-consumer-policy.
  • Select the checkbox next to the codeartifact-nextwork-consumer-policy that you created in the previous step.
  • Click Next to head to the Name, review, and create step.
  • In the Name, review, and create step:
    • In the Role name field, enter EC2-instance-nextwork-cicd.
    • In the Description - optional field, enter: Allows EC2 instances to access services related to the NextWork CI/CD pipeline series.
  • Next, in the review page, click the Create role button to create the IAM role.
  • After clicking Create role, you should see a success message at the top of the IAM Roles page, telling us that the IAM role EC2-instance-nextwork-cicd has been successfully created. Your new role will be listed in the roles table.

Attach IAM role to EC2

  • Now, we need to associate this IAM role with your EC2 instance.
  • Head back to the EC2 console.
  • Head to the Instances tab.
  • Select your running EC2 instance (nextwork-devops-yourname).
  • Click on Actions in the menu bar, then select Security, and then Modify IAM role.
  • In the Modify IAM role dialog box, select Refresh to load the IAM roles available for your EC2 instance.
  • Under IAM role, select the IAM role you just created, EC2-instance-nextwork-cicd, from the dropdown menu.
  • Select Update IAM role to attach the role to your EC2 instance.
  • After attaching the IAM role, you should see a green banner at the top of the EC2 Instances dashboard confirming that the IAM role was successfully modified for your instance.

Extra for Experts: How do IAM roles work with EC2 instances?

When you attach an IAM role to an EC2 instance, AWS automatically provides and rotates temporary security credentials for that instance. This means that applications running on the instance, like our Maven build, can automatically use these temporary credentials to make AWS API calls without you having to handle credential management.

That's why attaching an instance profile is considered a best practice compared to using hardcoded credentials (i.e. running commands in your EC2 terminal to manually assign it permanent credentials)!

Re-run export token command

Now that your EC2 instance has the necessary IAM role attached, let's re-run the command to export the CodeArtifact authorization token.

This time, your EC2 instance should be able to retrieve the token, since it has the necessary permissions from the IAM role.

  • Head back to your VS Code terminal connected to your EC2 instance.
  • Re-run the same export token command from Step 3.

Recap: What is a CodeArtifact authorization token?

The authorization token is like a temporary ID badge for your build tools to access CodeArtifact. When you run that token command, AWS checks your identity and issues this digital badge that's valid for 12 hours. Your build tools (like Maven) then present this token whenever they need to grab something from your CodeArtifact repository.

Why use temporary tokens instead of permanent credentials? It's all about security! If a token is ever compromised, it automatically expires in hours instead of giving permanent access. Plus, you don't have to worry about storing sensitive credentials in your build configuration files. The system automatically handles the authentication process behind the scenes, making your life easier while keeping your repositories secure. Just remember that you'll need to refresh this token if you come back to the project after more than 12 hours!

  • This command will retrieve a temporary authorization token for CodeArtifact and store it in an environment variable named CODEARTIFACT_AUTH_TOKEN.

Still getting "Unable to locate credentials" after attaching the IAM role?

This happens sometimes! There can be a delay before your EC2 instance recognizes its new IAM role.

Let's get this fixed:

  • Wait 2-3 minutes for the IAM role to fully propagate to your EC2 instance
  • Double-check in the EC2 console that the IAM role EC2-instance-nextwork-cicd is showing as attached to your instance
  • Review your IAM policy to make sure it has the correct permissions and no syntax errors
  • If nothing else works, you can try rebooting your EC2 instance as a last resort - but only do this if you're comfortable with the restart process

If you're still stuck, ask the NextWork community!

Fantastic! You've successfully attached the IAM policy and role to your EC2 instance. Your instance now has the permissions to access your CodeArtifact repository securely. Let's verify the connection in the next step.

See Packages in CodeArtifact!

Let's make sure everything is set up correctly by verifying the connection to our CodeArtifact repository from our EC2 instance. We'll configure Maven to use CodeArtifact and then try to compile our web app, which should now download dependencies from CodeArtifact.

This verification is crucial to ensure that our EC2 instance can successfully access and retrieve packages from CodeArtifact, which is a key part of our CI/CD pipeline setup.

In this step, you're going to:

  • Finish setting up the connection between Maven and CodeArtifact.
  • Compile your Maven project using the settings.xml file.
  • See your CodeArtifact repository automatically store your project's dependencies!
  • You might notice that we still have a few steps left in CodeArtifact's connection settings panel!

What are the code in Steps 4, 5, and 6 saying?

The code snippets define repository URLs, authentication details, and other settings so that Maven knows how to connect with CodeArtifact to fetch and store your project's dependencies.

Let's break each section down:

  1. The servers section is where your store your access details to the repositories you're connecting with your web app project. In this example, you've added your authentication token to access your local CodeArtifact repository.
  2. The profiles section is where you write a rulebook on when Maven should use which repository. We only have one package repository in this project, so our profiles section is more straightforward than other projects that might be pulling from multiple repositories! Our profiles section is telling Maven to go to the nextwork-packages repository to find the tools / packages needed to build your Java web app.
  3. The mirrors section sets up backup locations that Maven can check if it can't find what it needs in the first local repository it goes to. The backup location that we'll set by default is... our CodeArtifact repository again. This means that for any repository requests (denoted by the asterisk * in the * line), Maven will redirect those requests to the same CodeArtifact repository since it's our only local repository. It might seem unnecessary now, but mirrors are great in complex scenarios and is a great fallback option to set up from the start!
  • We'll use the code in each step in a minute, but we'll have to set up a special file called settings.xml first.
  • In VS Code, in your left hand file explorer, head to the root directory of your nextwork-web-project.
  • Create a new file at the root of your nextwork-web-project directory.
  • Name the new file settings.xml.

What is settings.xml?

settings.xml is like a settings page for Maven - it stores all the settings we saw in Steps 4-6 of the connection window. It tells Maven how to behave across all your projects. In our case, we need a settings.xml file to tell Maven where to find the dependencies and how to get access to the right repositories (e.g. the ones in CodeArtifact).

💡 Extra for Experts: What's xml?

xml is a markup language that lets you structure data and write instructions for a server. It's just like how html is a markup language that lets you structure data and write instructions for a web browser to display a web page.

You might also notice pom.xml, which is a file that was automatically created in your repository's root directory when you set up your web app for the first time.

pom.xml tells Maven the ingredients list (i.e. dependencies) for your web app and how to put them together to build the app. Then, once Maven knows what dependencies to look for, settings.xml tells Maven where to find the dependencies and how to get access to the right repositories (e.g. the ones in CodeArtifact).

  • Open the settings.xml file. If you created a new file, it will be empty.
  • In your settings.xml file, add the <settings> root tag if it's not already there:
<settings>
</settings>
  • Go back to the CodeArtifact connection settings panel.
  • From the Connection instructions dialog, copy the XML code snippet from Step 4: Add your server to the list of servers in your settings.xml.
  • Paste the code in the settings.xml file, in between the <settings> tags.
  • Let's copy the XML code snippet from Step 5: Add a profile containing your repository to your settings.xml.
  • Paste the code snippet you copied right underneath the <servers> tags. Make sure the <profiles> tags are also nested inside the <settings> tags.
  • Finally, paste the XML code snippet from Step 6: (Optional) Set a mirror in your settings.xml... right underneath the <profiles> tags.
  • Save the settings.xml file.

Recap: What is settings.xml?

The settings.xml file is Maven's control center - it's where you tell Maven how to behave across all your projects.

When we add CodeArtifact information to this file, we're essentially telling Maven: "Hey Maven, whenever you need to download a dependency, look in this CodeArtifact repository first, and here's how to authenticate yourself."

By configuring settings.xml properly, we're creating a seamless connection between Maven and CodeArtifact. Your builds will automatically authenticate and pull dependencies from the right place without you having to think about it again. It's one of those "set it up once, benefit forever" kinds of configurations that make a developer's life much easier.

Compile your project and verify the CodeArtifact integration

  • In your VS Code terminal, run pwd to check that you're in the root directory of your nextwork-web-project
  • If you're not at the root directory, run cd nextwork-web-project to get there!
  • Next, we'll compile your project.

What does compiling mean?

Compiling is like translating your project's code into a language that computers can understand and run. When you compile your project, you're making sure everything is correctly set up and ready to turn into a working app.

  • Run the Maven compile command, which uses the settings.xml file we just configured:
mvn -s settings.xml compile
  • Press Enter to execute the command.

Getting a "401 Unauthorized" error when running Maven?

This is a common authentication issue with CodeArtifact. Let's troubleshoot it together!

Try these steps:

  • Double check that your connection window is using the MacOS and Linux instructions - you should not be using the Windows instructions, even if you're doing this project on a Windows computer.
  • Verify your token exists by running: echo $CODEARTIFACT_AUTH_TOKEN - you should see a long string of characters
  • Double-check your settings.xml file against the CodeArtifact connection instructions - make sure server IDs, repository URLs, and profile settings are all correct
  • Check that your IAM role and policy are properly set up and attached to your EC2 instance
  • If all else fails, try clearing your Maven cache: rm -rf ~/.m2/repository and run mvn -s settings.xml compile again

If you're still stuck, ask the NextWork community!

  • As Maven compiles your project, observe the terminal output.
  • You should see messages like Downloading from nextwork-devops-cicd telling us that Maven is downloading dependencies from your CodeArtifact repository. This is a good sign that Maven is using CodeArtifact to manage dependencies!
  • If the compilation is successful and dependencies are downloaded from CodeArtifact, you'll see a BUILD SUCCESS message at the end of the Maven output.

Recap: What happens when Maven compiles with CodeArtifact?

When you run mvn -s settings.xml compile, Maven first looks at your project's dependencies in the pom.xml file. Then, instead of downloading them directly from public repositories, it checks your CodeArtifact repository. If the dependency isn't already in CodeArtifact, it will fetch it from the upstream repository (Maven Central in our case), cache it in CodeArtifact, and then deliver it to your project. This process happens for each required dependency, ensuring that your build process is secure, controlled, and faster for subsequent builds when dependencies are already cached in CodeArtifact.

  • See it to believe it! Let's head back to the CodeArtifact console in your browser.
  • Close the connection instructions window.
  • If you don't see any packages in your repository listed yet, click the refresh button in the top right corner of the Packages pane.
  • After refreshing, you should now see a list of Maven packages in your CodeArtifact repository.

Why are packages showing up in CodeArtifact?

Those packages appearing in your CodeArtifact repository are proof that the entire system is working! Here's what happened behind the scenes: when you ran the Maven compile command, Maven checked your project's pom.xml file and determined which dependencies your application needs. It then requested these dependencies through CodeArtifact.

Since this was the first time these dependencies were requested, CodeArtifact didn't have them yet. So it reached out to Maven Central (the upstream repository we configured), downloaded the packages, stored copies in your repository, and then provided them to Maven. It's like ordering groceries online - the store delivers what you need and keeps a record of your order.

Now that these packages are stored in your CodeArtifact repository, anyone else in your organization who needs the same dependencies will get them directly from your repository instead of from Maven Central. This gives you faster builds, more reliability, and the ability to control exactly which package versions your organization uses. Pretty powerful stuff!

  • These are the dependencies that Maven downloaded from Maven Central via CodeArtifact when you compiled your project.

Congrats! This confirms that your CodeArtifact setup is working correctly and that Maven is using it to manage dependencies 💪

Secret mission

Want to experience the full power of CodeArtifact?

Here's your chance to go beyond just consuming packages!

Your secret mission, should you choose to accept it, is to become a package publisher and add your very own custom package to your CodeArtifact repository. This mission will give you a deeper understanding of how companies manage their custom code libraries.

In this secret mission, you're going to:

  • Create your own custom package
  • Publish it directly to your CodeArtifact repository
  • Experience the full package lifecycle by downloading your own package
  • Showcase advanced package management skills in your documentation!

Become a Package Publisher

Delete your resources

Delete your resources

Now that we've successfully verified our CodeArtifact connection, it's time to clean up the AWS resources we created to avoid incurring any unnecessary costs.

Resources to delete:

  • EC2 instance
  • IAM role and policy
  • CodeArtifact repository and domain
  • Key pair file

EC2 Instance

  • Head to the EC2 console.
  • Select Instances from the left hand menu.
  • Select your instance (nextwork-devops-yourname).
  • Select Instance state > Terminate instance.
  • Select Terminate to confirm.
  • Wait for the instance to show "Terminated" status before proceeding with other cleanup tasks.

Why terminate your EC2 instance?

EC2 instances continue to incur charges as long as they're in the "running" state. By terminating the instance (not just stopping it), you ensure you won't be billed for compute resources you're no longer using.

IAM Resources

  • Head to the IAM console.
  • Select Roles from the left hand menu.
  • Search for EC2-instance-nextwork-cicd.
  • Select the role.
  • Select Delete.
  • Confirm the deletion by typing Delete and selecting Delete.
  • Next, select Policies from the left hand menu.
  • Search for codeartifact-nextwork-consumer-policy.
  • Select the policy.
  • Select Delete policy.
  • Confirm the deletion by typing Delete and selecting Delete.

Why clean up IAM resources?

While IAM roles and policies don't incur direct costs, maintaining unused permissions increases your security risk surface area and complicates access management. Following the principle of least privilege means removing access rights when they're no longer needed.

CodeArtifact Resources

  • Head to the CodeArtifact console.
  • Select Repositories from the left hand menu.
  • Select nextwork-devops-cicd.
  • Select Delete repository.
  • Confirm the deletion by typing delete and selecting Delete repository.
  • After deleting the repository, select Domains from the left hand menu.
  • Select nextwork.
  • Select Delete domain.
  • Confirm the deletion by typing delete and selecting Delete domain.

Why delete CodeArtifact resources?

CodeArtifact charges are based on storage and API requests. Even if you're not actively using your repository, you'll continue to pay for storing any packages that were cached during your project work.

Local Files

  • Go to your Desktop or wherever you stored your project files.
  • Delete the DevOps folder containing the nextwork-keypair.pem file.
  • You can also delete any local copies of the web app code.

Why delete key pair files?

The .pem file is essentially a private key that provides access to your EC2 instance. Even though the instance is terminated, it's a security best practice to delete private keys when you no longer need them to prevent any unauthorized access if you ever reuse the key name.

Get your documentation!

Get your documentation!

Congratulations! Your project is now set up to use CodeArtifact for dependency management, which is a crucial step for setting up a robust CI/CD pipeline.

In this project, you've learned how to:

  • 🗂️ Set up and configure AWS CodeArtifact as a private Maven repository for managing dependencies.
  • 🛡️ Use IAM roles and policies to let your EC2 instance access CodeArtifact.
  • ✅ Verify your web app's connection to CodeArtifact and ensure Maven can download dependencies from it.
  • 💎 Create and add your own packages to your CodeArtifact repository!

Ready to quiz yourself? You got this! 💪

In the next project, you'll learn how to set up CodeBuild to automatically build your web app. No more running commands to get CodeArtifact to compile your project!

See you in the next project of the 6 Day DevOps Challenge - Continuous Integration with CodeBuild!

p.s. Does it say "Still tasks to complete!" at the bottom of the screen?

This means you still have screenshots left to upload, or questions left to answer!

  1. Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
  2. Search for the text Return to later.
  3. Jump straight to your incomplete tasks!
  4. 🙋‍♀️ Still stuck? Ask the community!