Security on AWS - AWS WAF x AWS App Runner
Tags: aws, apprunner, waf, security
Published: 2023-05-18 01:28:34

![](https://lh3.googleusercontent.com/6fY7GaAUB-hxOV7DwYQwmujYD9yD0vdaDaTRhDbRVq_paOH6Tn1RNBM48Cx7quTHRxNZth6sqBMNVHZiWsGhx-UI9TeKg_LYALA70G_cu4LLtzzGMtCKabWfn1upNDiatS4a4aAiyLy6v8JNgenit7M)

Now all need websites for everything like business, education, government, non-profit, and many more. Creating a website can use a virtual machine, a container, serverless, or many other technologies. For this tutorial, I use containers when creating a website because containers can run on-premises or through cloud providers.

The reader will learn how to create a web application firewall with AWS WAF and AWS App Runner as a web application. [AWS App Runner](https://aws.amazon.com/apprunner) is an AWS service that deploys web applications or API using Amazon ECR or GitHub only. While [AWS WAF (Web Application Firewall)](https://aws.amazon.com/waf) is an AWS service that can protect the web application.

## Requirements

Before getting started with this tutorial, you need:
- an [AWS account](https://aws.amazon.com).
- [Terraform](https://developer.hashicorp.com/terraform/downloads).
- your IDE.
- use [my repository](https://github.com/budionosan/helloworld) for example.
- My blog about [Amazon ECR](https://aws.amazon.com/ecr) [on this link](https://dev.to/aws-builders/containers-on-aws-amazon-elastic-container-registry-ecr-and-aws-app-runner-33eo).

## Implementing AWS App Runner with Terraform

You are learning how to create an IAM role, push an image to Amazon ECR and create an AWS service using Terraform (for this tutorial, you create AWS App Runner service).

### AWS IAM (Identity and Access Management) & Amazon ECR (Elastic Container Registry)

[AWS IAM (Identity and Access Management)](https://aws.amazon.com/iam) is an AWS service that gives users access to other AWS services. I need an IAM role because I need permission from AWS App Runner to Amazon ECR image.

[Create an IAM role](https://us-east-1.console.aws.amazon.com/iamv2/home#/roles/create?step=selectEntities) for the AWS App Runner service that can access Amazon ECR images. But I need a trust policy because when I choose AWS service, AWS App Runner is not available. Choose custom trust policy and copy this trust policy for AWS App Runner:

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
		"Effect": "Allow",
		"Principal": {
			"Service": "build.apprunner.amazonaws.com"
		},
		"Action": "sts:AssumeRole"
		}
	]
}
```

![](https://lh3.googleusercontent.com/pw/AJFCJaUzv-kJbMEh45ownxIKAE-J9v2Fs6fY3OInv91FbGDXL4EXxi55FwcN3Ksc6cKeIAaKjl-52MqvaZ_MFtOLM_Vw1brPSWOvnzY60S1fVLWLLbSVyCueuvz_lJgS0eOlCxKDSuOZjZr4bS6WLESO4_k=w1057-h704-s-no?authuser=0)

Then click Next for the next step. This next step is to add a permission policy with copy `AWSAppRunnerServicePolicyForECRAccess`. This permission policy is used because it needs permission from AWS App Runner to the Amazon ECR image.

![](https://lh3.googleusercontent.com/pw/AJFCJaUL7h7MAY4Xug_uYAOJ-k9y1f-GaS-_I4aBef1cXyuY3fsKt3MLJO2tUEX5nb6f7TkOCNnXwaG2hWhCE4y3b3qC_19imiuYqsoY3_ztlFefz0SaGol11cGzuQDoK3_Q36QLcbgVghlTYy_Z2vSwACs=w649-h404-s-no?authuser=0)

Then click Next again. Fill in the IAM role name `AppRunnerECRAccessRole` and click **Create role**.

![](https://lh3.googleusercontent.com/pw/AJFCJaXv8rl0cyCBh8ujcWNiawMB3wf3aSp3zJgBQ3arKjeByIywc8wFzoi4fkWRe4b4R1wBEgNI4ubGwWIfyRBim-KEY_s4C9G6FFHfUdGe_wi8iCO-A-MKidWDQBhLnkFpJMe9xS4b4UqrMaV_IFJkBwo=w809-h338-s-no?authuser=0)

![](https://lh6.googleusercontent.com/H2wT-TmFpwRQ9BHz0asR8-ESgmFuveQSiomXWoXx34LNy-tTtE9e9smIFXwJ-vgk1eoAqEMeKt00KKZTRYCwCoxq5k5yvfhSA6GXGzOtxTw_LjJ2e8zWqZB_kzXf8rCZ5h6fBJWBNihABXUaR_31ym0)

After creating an IAM role, you can see the IAM role already created. Click **View role** and click copy `arn:aws:iam::YOUR_AWS_ACCOUNT:role/service-role/AppRunnerECRAccessRole`. This IAM role is used when creating the AWS App Runner service because authentication configuration is required.

![](https://lh3.googleusercontent.com/pw/AJFCJaUkotUMzE67-1Jv811ExreB0k400FfJEDiDfCPgvW9Qo7riJmU7lgCP9n2KVCB0TegcBCheJ8mKS3yy6HeE_9qQB-Fp98lk71l7ljBu1jPF0CaV2J5Fhs104pxk5kGDD1QfcEfLS_GwpwnVwjybOsg=w1364-h396-s-no?authuser=0)

Open your IDE. Clone [my repository](https://github.com/budionosan/helloworld) with the command `git clone https://github.com/budionosan/helloworld.git`, then open the `helloworld` folder with the command `cd helloworld`.

```
git clone https://github.com/budionosan/helloworld.git
cd helloworld
```

![](https://lh3.googleusercontent.com/pw/AJFCJaVKcAVsuxPWkusnID_4uaO-eJMYoxQo5a5T2tY79NU70415h35EyQ5TExBWSx6V8UVEKx4QGX0JzdwfObSPNsiTnu090EmU7lFYNujs5HKGZzhLN6311pJIeKL7h10qOdPJcnO_zLiTRKBn3EG_2aE=w210-h315-s-no?authuser=0)

Then navigate to [Amazon ECR](https://us-west-2.console.aws.amazon.com/ecr/home?region=us-west-2). You can read how to create a repository and push images to [Amazon ECR](https://dev.to/aws-builders/containers-on-aws-amazon-elastic-container-registry-ecr-and-aws-app-runner-33eo). 

**NOTE:** After create ECR repository, you can click **View push commands**. After pushing the image to Amazon ECR, you can check [ECR repository](https://us-west-2.console.aws.amazon.com/ecr/repositories?region=us-west-2).

![](https://lh3.googleusercontent.com/pw/AJFCJaUmr1_8OVuSgzk8-_WN4IUYIGQqXXB2Du-sW4zJi70dIY5p05KK8zYS8rzZnEBFuQIW7GXmiTeYGNrEEek2_wB7-wSwscO9YL-at3hQLf5s-rFt4qJ9Uj9TO046v9Ykx78MrkHl4YSAgwFTdj6fVO8=w861-h410-s-no?authuser=0)

Click your repository name and click **Copy URI**. This ECR image is used when creating the AWS App Runner service because it uses container images.

### AWS App Runner

Back to the IDE environment with command the `cd ..` . Create a folder called `apprunnerxwaf` with the command `mkdir apprunnerxwaf`, then navigate to the `apprunnerxwaf` folder with the command `cd apprunnerxwaf`.

```
cd ..
mkdir apprunnerxwaf
cd apprunnerxwaf
```

![](https://lh3.googleusercontent.com/pw/AJFCJaVKcAVsuxPWkusnID_4uaO-eJMYoxQo5a5T2tY79NU70415h35EyQ5TExBWSx6V8UVEKx4QGX0JzdwfObSPNsiTnu090EmU7lFYNujs5HKGZzhLN6311pJIeKL7h10qOdPJcnO_zLiTRKBn3EG_2aE=w210-h315-s-no?authuser=0)

Install Terraform [on this link](https://developer.hashicorp.com/terraform/downloads) in your IDE. Terraform is available on Windows, Linux, macOS, and many other platforms. After installing Terraform, check the Terraform version with the command `terraform --version` for whether Terraform is already installed or not.

[Create a Terraform file](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apprunner_service) to create an AWS App Runner service in your IDE:

The source code of the Terraform file can be seen [on the link](https://github.com/budionosan/writing/blob/main/main.tf).

```
terraform {
	required_providers {
		aws = {
			source = "hashicorp/aws"
			version = "4.61.0"
		}
	}
}
```

`required_providers` means cloud provider name such as AWS, Google Cloud, Azure, or other cloud providers. For this tutorial, I chose AWS because I want to create an AWS App Runner service. You can see Terraform on the AWS latest version [on this link](https://registry.terraform.io/providers/hashicorp/aws/latest).

```
provider "aws" {
	region = "us-west-2"
}
```
`providers “aws”` means the AWS region for creating AWS resources, for example “us-west-2” (Oregon) or "us-east-1" (North Virginia).

```
resource "aws_apprunner_service" "apprunnerxwaf" {
```
`resource "aws_apprunner_service"` means Terraform for [AWS App Runner service](https://us-west-2.console.aws.amazon.com/apprunner/home?region=us-west-2#/services).

```
service_name = "apprunnerxwaf"
```
`service_name` means AWS App Runner service name.

```
source_configuration {
	authentication_configuration {
		access_role_arn = "arn:aws:iam::YOUR_AWS_ACCOUNT:role/service-role/AppRunnerECRAccessRole"
	}
```
`access_role_arn` means your IAM Role for AWS App Runner can access Amazon ECR **that already created**, example `AppRunnerECRAccessRole`.

```
image_repository {
	image_configuration {
		port = "8080"
	}
	image_identifier = "YOUR_AWS_ACCOUNT.dkr.ecr.us-west-2.amazonaws.com/ECR_REPOSITORY_NAME:latest"
```
`image_configuration` means port listen while `image_identifier` means your [Amazon ECR image](https://us-west-2.console.aws.amazon.com/ecr/repositories?region=us-west-2) URL **that already created**.

**NOTE:** Change `YOUR_AWS_ACCOUNT` with your AWS account ID 12 digits (example: 098765432123) and also `ECR_REPOSITORY_NAME` with your Amazon ECR repository name.

```
	image_repository_type = "ECR"
	}
	auto_deployments_enabled = false
	}
	tags = {
		Name = "apprunnerxwaf"
	}
}
```
`image_repository_type` means ECR (private) or [ECR_PUBLIC](https://gallery.ecr.aws) (public) while `auto_deployments_enabled` means enable automatic deployment with CI/CD (true) and disable automatic deployment (false).

Initialize the Terraform file with the command 

`terraform init`

 `terraform init` means install cloud provider plugin (for this tutorial, AWS). If initializing this Terraform file is successful, show notifications below this screenshot. But if initializing the Terraform file is not successful, check your Terraform file typo.

![](https://lh3.googleusercontent.com/ACTbunsWHGvFpYqLJWqAS83yGn92Bs5U-eeVxsI761YA5QkHyQqSF-yYdbdt884AkrJ84iBDOsrR_LLqy0ehU2Yxg1i5mOog_noAMRZUVfBXJHsbdeAqgdL8T41MwAEkThKYCJwmsSqfP1KUJUFuR_4)

Apply the Terraform file with the command 

`terraform apply`

`terraform apply` means create cloud provider services (for this tutorial, create AWS App Runner service).

![](https://lh5.googleusercontent.com/6vf-1Mcr2CxDyXrJmlZlh1SO1PYzdurThb8OAOA-KQOIJ1Z4MOFPUwH6V8mb9dqMMu5cb68dgVNmvOWXoj-ZLcelHIEr7mof-CHKtTGMt4CdC9o_ofpnG9ewmScjTJbVY2qwEcwnaLu8SkvN1C5vPkY)

![](https://lh6.googleusercontent.com/Q29XbzKh-v-SncohGNR2M6bBEXqAXPHe_eMTV6HBkchUjeYhPW0Z1azBHtugp8D972C3Si7n6Z7JM4s8dGc6Sqh3NDBmk9xVjyVKxD6t_ewUp_8gA67e8y1vuEzOgiyRFWmGLcIR39na_bLmlqqlwdU)

Enter `yes` in the prompt above to create the AWS App Runner service. After entering `yes`, Terraform will create an App Runner service.

![](https://lh6.googleusercontent.com/coA-JPknpKoQCY7qVF_ziCuISXcJAF3daAqaDheBAPcEu45pnht_QZt5w2KJMDMrOCO7myk9D3mYR0f-LCyMzrPwWB1ycQGjwmc_d7emezq8ZEbHo2PnRl9zaBfH9PnC5DqePxj3eu4yuhE0psaX16w)

[Navigate to AWS App Runner](https://us-west-2.console.aws.amazon.com/apprunner/home?region=us-west-2#/services) to check the service. The service name *apprunnerxwaf* is running. The default domain has been managed by AWS, but you can customize this default domain to your domain.

![](https://lh3.googleusercontent.com/pw/AJFCJaWvratsUFUklPlu31YT_iLC0ywugXWNdcjPj4DGMAig768OR0ns_urni8yPc95ik41PMkBt-Opgcb3zd2iRatxX4UKJUNvYRS4eos02Dd-FLd8qFIV4Oy3yI0k5lUbp6Kfo3KTNmJI8jG0wbtL7NZY=w1081-h307-s-no?authuser=0)

Click the default domain URL, which automatically opens a new tab as shown below:

![](https://lh3.googleusercontent.com/pw/AJFCJaWH7xA0npaITvueelDkOKQkZX_wgEThhevtNK_ENnScDbt9Cp1ilicMY3PZGuSJvxfM1KA9DCgi06nA31n9gef-karCGwMLcY6fmrlMdBzU7z3zFFPRUoKwE-T6jdxPLOP0xlDSnCtg1r4eOwQKieQ=w494-h110-s-no?authuser=0)

## Implementing AWS WAF CAPTCHA

You are learning how to create a web ACL and rule of web ACL using CAPTCHA based statements.

### AWS WAF (Web Application Firewall)

![](https://lh4.googleusercontent.com/8od2cJP23Dw_bXcTGOn-TRM59C7EXtycZAWAwwJ16WemaagdOFGZtapW-GBqONrX1RDY97PIBo76flxfQd7C5vZe3rMwg8vgjsTc2G1uzrtewSwbhDNt1vy-ygNqjY_F_7UdsgeSk90TpL_4gD2tkl0)

For the website to be safe from attackers, I must focus on security to protect the website. I use security features such as CAPTCHA. [CAPTCHA](https://support.google.com/a/answer/1217728?hl=en&sjid=2541944959726369385-AP) is a security feature that must be solved by a real human (not a bot) before entering the website. Navigate to [AWS WAF](https://us-east-1.console.aws.amazon.com/wafv2/homev2/start?region=us-west-2).

I use AWS WAF to add CAPTCHA features to the AWS App Runner service. AWS WAF is integrated with AWS services such as:
- Amazon API Gateway
- Application Load Balancer (used in Amazon EC2, Amazon ECS, Amazon EKS and AWS Fargate)
- AWS AppSync
- AWS App Runner
- Amazon Cognito
- Amazon CloudFront

Click **Create web ACL**. Fill in the web ACL name, description, and CloudWatch metric name (for this tutorial, I don't use CloudWatch because the focus is on AWS WAF only). Choose regional resources because I want to be integrated with AWS App Runner. Choose **US West (Oregon)** for the region and click Next.

![](https://lh5.googleusercontent.com/iZsIGeqHtFDGegXSBDD_QUXhfwsmGgaDf1luz6cdP-drVM38RhNTdTbbdUq-LdU_1ks6QBNp83UyCb31kRsQ7z0Ht1pl6jFnt2OLnOmdfPmPP2gL0i-qJoG2w1fkdKX0Acae16kret2SsPwdw9W-Gl4)

Click **add rules**. Add rules in two ways: managed rule groups or my own rules. My own rules means I can create them as needed while managed rule groups means rule groups are managed by AWS and another company. Choose **Add my own rules and rule groups**.

![](https://lh6.googleusercontent.com/PprJaPo4ggcMytBuWVzcbWHW2bJBE1IVQexvIAioeilft6CQTtDDCl7_BnlU2LA3Voih7qZ8ev5mJXuyikclnYNSU82GOy-rPlMNfPTfWHdTDURpAivgWlvKK9ksHqwUsJHiFD-UzkP80yTRcfJe-jo)

Choose **rule builder**. The rule builder can customize the rules of the web ACL. To be able to use AWS WAF integrated with AWS App Runner, I have a rule: **if a user from Indonesia accesses the web application of AWS App Runner, then the user must pass CAPTCHA for access. If a user is from another country, the user can access the web application without needing to pass the CAPTCHA**.

![](https://lh6.googleusercontent.com/zV9cREVBQoiG29ukXXJqj6HrXZUcxUTedWOHeoGdZYjI8zDDjvocHj81bqClQFcBInnTuunqwvNnhOZrqPAXcJC46q0QUnl1rjZk4So0JrzdZa0cGUliPIdApUB-de4E75DjpyQZhMjK1kbOX8YpIFc)

Fill in the rule name. The statement rule has an option:
- matches the statement. Example **IF** a request has statement `X` **THEN** action `Y` but **IF** a request has the statement `A`, action `Y` can not run.

- matches all the statements. Example **IF** a request has statements `X1` **AND** `X2`, **THEN** action `Y` can be run, but **IF** a request has a statement `X1` only, action `Y` cannot be run.

- matches at least one of the statements. Example **IF** a request has statement `X1` **OR** `X2` **THEN** action `Y` but **IF** a request has a statement `X1` only, action `Y` still can run.

- doesn’t match the statement. Example **IF** a request does not match the statement `X` **THEN** action `Y` but **IF** a request has the statement `A`, action `Y` can run.

![](https://lh4.googleusercontent.com/tuJ08wBNIKLwSwmIFPU74_fOGrG5AGX8dD7d_4dyyRdAjnA5M-DkFDgbz28HospCj8FztJxabi_v-qS0FeKF3g1-w6loLZRkzMV7dGeXAPwca5Qb0DPtW260fCnRCSP_S-t48w9HQptCzk1-_AA_QZ0)

Choose **matches the statement**. The statement has options to inspect such as country, IP address, label, etc. For this tutorial, use the country option to test whether WAF is running or not. Choose country codes. In this example, choose Indonesia - ID (you can change your country) that is based on the source IP address.

![](https://lh5.googleusercontent.com/yRTbyMS_DP7im8SQeSjW6Xe_3S0gXk26m6I_ue0txnupJK6NsNUuivXupzuN7usTXsVnUYGz1wRBIbCpiq4gp3ggqJ3ggldQZARfqbyRi8ajGOviKzu6NXVvCxXVXikdBt_tR_NBe-kbJKioiWhU3-I)

![](https://lh5.googleusercontent.com/wPAFcTV2dhbnprvpZ1Qo4ouqb9xt0cQyEwkhzBX_FJW8k5gvAHM7Fv7C2fVb7muiVX_IrLbqpcD1g4IytCjAG6jMTb2xqHEs1jS7F4oLDZ4cW-D88eLQMc1-UQouFB6rUigVO02aG8Tg-_xs5ZWRofE)

The rule has action options:
- Allow: The user can access the web application if the request matches the statement rule.
- Block: The user cannot access the web application, and the web application is not available or responding if the request does not match the statement rule.
- Count: The user does not have an effect when accessing the web application because this action is counting requests only.
- CAPTCHA: The user can access the web application if the user can pass the CAPTCHA.
- Challenge: The user can access the web application if the user must enable JavaScript to verify that you are a human (not a bot). If the user does not enable JavaScript, the web application can't be accessed until JavaScript is enabled.

![](https://lh3.googleusercontent.com/pw/AJFCJaXzs1ckOvAOB1W12pCZ36VllY7vQvuJOpFyRGhIAR0q9jCOMrB0kiTuRPJA1wi7p9w8aynaLbh18K_QkCtDvGHoTSfGAWWOad_43WYLbMZT3oZQC42sbUs-DxyVO1xDmA4l8OwqRvwgEiEPD_lg_w92=w1162-h206-s-no?authuser=0)

Choose **CAPTCHA** for an action in the rule. Click **add rule** and you can see the rule is already created.

![](https://lh4.googleusercontent.com/IQ0LqAS_fhNDqLQaoPvXQvu7H3_xncX_exKX0VCPldiJy4nsMod46lFD-uS6EQz1jgdmjsUXR4u5AT8j8J2w31e2Ckovobq7PSctvrF1Ba1dpy_XCSTbJvAO_nEAnDYiIUbh2Zh0YA9ME3yj8xzBJWY)

![](https://lh3.googleusercontent.com/vdLnNePgSREYluJ7FKEbxcWR8k9IDmBmqkzwQVU0ZtRFMbJC3mkdGF9m217SzLEgykO-FSOK9AOFheFDnVYCbkEq6cNOImzlV4cW_9oWnF0AA_RN4kK9dUhiFGbHoyAdJoNbqFqzo6piu7GMAtqMF3U)

The default action is to take action if the request doesn't match the statement rule. This condition can be explained:
- Allow: if you are from another country (except Indonesia) and want to access the web application, you can access the web application without passing the CAPTCHA.
- Block: if you are from another country (except Indonesia) and want to access the web application, you cannot access the web application.

For this article, the default action is allow and click Next.

![](https://lh4.googleusercontent.com/mmezIKZlP8Q-Mp0lSd_t2gN_M0mc8rGDIK5l0YR_OYktt0sbbpO2ggaNb_JN-vYq7DgMqAphtBKiNnXP8ilMLDkQFDv8d45shoM1zJMY7wLuu9a0tQsvzYXvCPKRoNNt3jFmt7qxE9RaSXOFH8twzfY)

Because only one rule, steps 3 and 4 are skipped. Click Next. Step 5 is to scroll down and click **Create web ACL**.

![](https://lh5.googleusercontent.com/nHZzLBP3mpByRC1-bIdjyEJQXuWM5Q6XBHiKHsnxWeGihhjOCZ8QRkKRoNewh_pxOpR7g837FlebvDNax0eCFD0b0kSSzbHCW2upaOI3e2qCXXCH1EHqWNfO_dN470PFI6OGyiIfvR3U4LB8MkLN5kM)

Click the web ACL name.

![](https://lh6.googleusercontent.com/uuHaDJPfM8UMoivXxoRXgdJZpeP7csX0Zw0V3ytzhsVwj_22bmtqqBVHsN463KPdXCY6IXiNv-y02kGnbOv6gulV2FIQnCch1GzubNpariIYPSv-o7dS3G09uLz3IAyHgoajt0fUy5KfKYZz-DOye30)

Then click add AWS resources.

![](https://lh3.googleusercontent.com/jEYhhR9v9Ji9sRsojF-uP591xxD3N-CGiKdB97vKHEsbwwJw_aH3PldVgwjL9QfOo0fcGI4RcF7lclw633ptW7V32IyFpPJL1--Dyth8Q4bJwFssrbpfWYeKNdt3lpOAi1oSneyqyQdpch5ps-fNy8Y)

Choose the Amazon App Runner service and choose the App Runner service name. Click add to enable integration with AWS WAF.

![](https://lh3.googleusercontent.com/HFNeBcbeVhAEx6VBQ-t3r5lwmWr2KkALMZfQ84Fo446MjzXsaxc3oc8BCsTlNe30pdhe56PPglIeofRlxn1J3-B_PkKITvTlJhCsnRQmNMzr8BUXQzs3WcL_fuVb_PyDB8AuKY3A_9hkujMIniL17bQ)

Then go to rules and click the rule name.

![](https://lh4.googleusercontent.com/ilMaT6Meu_ghoAuCyVUVLOYLZ3BQLGsHqH-qRw52BdN0dNCm3GkGbGoJ_WBptboCUgaPPAjvztbaowNa6nVO54wJlrlAuMLdysbiMvZ_c8sVGHKQd0XJq9_OIbjVEFdE4ecp60UAgJDH6Av-BCizr4w)

This role explains that if a request matches the statement (in this case, the request option from the country is Indonesia), the next action after the request match is CAPTCHA.

![](https://lh5.googleusercontent.com/BsQZwJgsb_CE-kjBdprTl4obKFIQbWaPiDogU-AZrAFrd2CPQIO5GbWMQPXkRRxJWbFKtFL1hGYB3msJbaq2RV2Sxi1E1MJO1IVP-I2shpuPKVNt24IhcYz_GgchcYLBUzrm-jGpB9dIm_CWfGRAOws)

Navigate again to [AWS App Runner](https://us-west-2.console.aws.amazon.com/apprunner/home?region=us-west-2#/services) for testing the web application with WAF. When you open the URL link, see the available page that needs a CAPTCHA to confirm you are a human (not a bot). Click Begin for the next step.

![](https://lh3.googleusercontent.com/pw/AJFCJaXB8uDOhZAK_cY0eSUMpBTLCt6uCMwsdJi-5o3kGJjkDZPrwncQhsVmEbjU5UZMvgJU6HZS6Hc8s0rs1Ol7DD-FGyfPTt8HnDiYSbR0z9TBLJQMI5qfyeYHLhyrd9XdqcUdpTMECgGj3DNZGMVCz_s=w1049-h604-s-no?authuser=0)

**NOTE:** If your web application is not like the above screenshot, you can click refresh because the web application needs time. 

You must solve the CAPTCHA with a puzzle type like this screenshot. This puzzle type must match top and bottom and become one with a slider. Click **Submit**.

![](https://lh3.googleusercontent.com/pw/AJFCJaUPPfZ4a6B-zPJljOFZ2k91RxLdT8TyHMGdq5LAdmPzQtl7zIa8Em_bYwnJNfgpkDoVVTR7aA2_kZUbE6_D7Y1JOpKBw8DpYvAhmMfiyPjvyOBLAtl5TNU9agAuKDHrQOukucL6e0sQdBXzHLUCNGGj=w1053-h517-s-no?authuser=0)

After you pass the CAPTCHA, you can access the web application of AWS App Runner.

## Conclusion

In this tutorial, you already learned how to push images to Amazon ECR. Amazon ECR is an AWS service that is very useful for storing your container images and can be used with other AWS services such as AWS App Runner. You can get started learning containers by learning AWS App Runner. You also already know how to create AWS services using Terraform as an [Infrastructure as Code (IaC)](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/infrastructure-as-code) and how to use AWS WAF to integrate with AWS App Runner as a web application to protect from anywhere attacks.