Using Cloud Armor to allow/block specific countries/regions from accessing application deployed on GCP App Engine
In the App engine, we have firewall rules to allow/block traffic based on IP ranges. But what if we want to allow/block traffic from specific countries/regions?
In order to achieve this we can use Cloud Armor. Cloud Armor helps protect your applications and websites against denial of service and web attacks. You can check the GCP documentation to learn more.
Note : It is assumed that application is already deployed and running on App Engine.
We need to follow 3 major steps:
- Creating Load balancer which will serve App Engine application as backend
2. Configure Cloud Armor policy to allow/block specific countries/region
3. Disable the default appspot url of App Engine
Lets get started!
Step 1: Creating Load balancer which will serve App Engine application as backend
Cloud Armor cannot directly be applied to App Engine endpoint. Hence, we will have to create a Google load balancer and add our app engine service as a backend. We will create serverless NEG for this purpose
Tips: A serverless NEG is a backend that points to a Cloud Run, App Engine, or Cloud Functions service.
For more information, you can refer to this GCP documentation
- Create Serverless Neg
Use below gcloud command to create serverless Neg
gcloud compute network-endpoint-groups create <SERVERLESS_NEG_NAME>\
region=us-central1 \
--network-endpoint-type=SERVERLESS \
--app-engine-service=default
Note: default is the app engine service you want to have behind LB.
Us-central1 is the region where app engine is deployed
2. Create a Backend Service that points to your Serverless NEG
Create backend service for Load Balancer using below gcloud command
gcloud compute backend-services create <BACKEND_SERVICE_NAME> \
--global
Add backend to service using below gcloud command
gcloud compute backend-services add-backend --global \
<BACKEND_SERVICE_NAME> \
--network-endpoint-group=<SERVERLESS_NEG_NAME> \
--network-endpoint-group-region=us-central1
3. Create a URL map to route incoming requests to the backend service
Use below gcloud command to create url map
gcloud compute url-maps create <URL_MAP_NAME> \
--default-service <BACKEND_SERVICE_NAME>
If you want to create an HTTPS load balancer, you must have an SSL certificate resource to use in the HTTPS target proxy. To create a SSL certificate, you must have a domain (If you don’t have a domain, you can use a self signed SSL certificate).
We can create self managed or google managed SSL certificates.
For now, I will create an HTTP load balancer. Hence will not require any SSL certificate.
4. Create target proxy
Use below gcloud command to create target proxy
gcloud compute target-http-proxies create <TARGET_HTTP_PROXY_NAME> \
--url-map=<URL_MAP_NAME>
5. Create global forwarding rule
Use below gcloud command to create global forwarding rule,
gcloud compute forwarding-rules create <HTTP_FORWARDING_RULE_NAME> \
--target-http-proxy=<TARGET_HTTP_PROXY_NAME> \
--global \
--ports=80
Our Load balancer is set up now.
You can get the IP address at which your load balancer is serving either by going to GCP console in Load balancing under Frontends or you can use below command,
gcloud beta compute forwarding-rules describe \ <HTTP_FORWARDING_RULE_NAME> --global
It will print a field containing an IP address.
Eg.
IPAddress: xx.xx.xx.xx
Step 2. Configure Cloud Armor policy to allow/block specific countries/region
Now as our Load balancer is set up. It’s time to configure security policies that will be applied to this load balancer. We will configure security policies on Cloud Armor to allow/block traffic from specific countries. (Apart from allow/block specific region traffic, there are many other features in cloud armor. You can refer to this GCP documentation for more information)
- Go to Cloud Armor from GCP console
- Click on Create Policy
3. Give name and description to policy.
Select default rule action as deny. You can choose any Deny status code. I will choose 403 (Forbidden).
The default rule action will have lowest priority. If you want to allow only specific countries, you can set a default action as deny. But if you want to allow all except some specific countries, you can set default as allow
Here for eg, I will only allow US to access the application. Hence my policy default action will be Deny.
Click the next step.
4. On the second step (Add more rules), click Add rules
Here, since I want to allow only the US, I will create a rule for the US as follows.
Give description to rule. Select mode as Advanced mode. Click on Rule syntax help (You can refer to the picture)
You can see the syntax for all the examples.
Syntax rule based on country selection is
origin.region_code == '<country_code>'
Hence, for US is
origin.region_code == 'US'
Click Action as Allow.
Priority as 100 (Priority is evaluated from 0 (highest) to 2,147,483,647 (lowest))
Click on Done
The summary will look like this
You can add multiple countries to allow traffic by adding clicking Add rule
Note: If I had to allow all countries except the US, then the default rule would be Allow and in add more rules, I would have created a deny rule for the US.
5. Once all rules are added, click on Next step
6. In Apply policy to targets, click on Add Target
Select Type as Load balancer and Target as the Load balancer just created above which is serving the App engine.
After select target, click Next step
7. Next, Advanced configurations are optional.
You can click Create Policy.
Cloud Armor Policy is created !!!
Now for all countries which we denied access will get 403 Forbidden error and they won’t be able to access our application.
We are not done yet. One main step is remaining.
Step 3: Disable the default appspot URL of App Engine
By default, App Engine applications serve requests at a URL of the form https://$PROJECT_ID.appspot.com. This URL is automatically assigned when you create an App Engine app. We need to disable this appspot URL so that all user traffic goes through the load balancer. Otherwise, users can use the appspot URL to bypass the load balancer, including the Cloud Armor policy of allow/block traffic configured in above steps on the load balancer. Hence this is very important.
Update the default service of an App Engine app to accept traffic only from Cloud Load Balancing run below gcloud command:
gcloud app services update default --ingress \
internal-and-cloud-load-balancing
We are done!
Conclusion
It was quite a long blog. I hope this was helpful for you all. It’s possible that I might have missed something. Please feel free to comment if so!
Thanks for reading!