Monday, 16 May 2022

How to whitelist AWS IP address (or IP range)

 You do care about security. And also your organization does.

This is why you system admin doesn't allow ANY traffic from the organization network to the internet. Except the traffic implicitly needed for organization ongoing activity. It is also possible that your organization consumes some service, which is not free and you pay for each request you make. In this case only relevant services/users/workstations should be allowed to access specific IPs from specific workstations.



Usually, you want to access AWS endpoint that is exposed as CloudFront, API Gateway or ELB. So you want to add to your organization whitelist the IP of this service. But there is a problem. The IP is not static. It changes in the non predictable way. So how would you whitelist the IP?

There are 2 options to do it. 

1. Use Network Load Balancer (NLB). NLB  is layer 4 load balancer which is part of the AWS ELB (Elastic Load Balancer) services. We are talking about it because you can set a static IP for each availability zone NLB is balancing. 

When creating NLB you can choose to get the static IP from the AWS pool or from Elastic IP


AWS Elastic IP is a static IP that you can create through AWS console (or CLI). Note that Elastic IP costs extra money.

But what happens if my solution has ALB (Application Load Balancer) and not NLB?

Not a problem. ALB can be set as a target for NLB



But Elastic IP is assigned randomly. It means you can get one IP like 3.3.3.3 and another one like 172.45.3.5.

Organization don't like random IPS. They do like ranges of IPs. Like 172.45.3.5-172.45.3.8.

So how would you get a proper range.

One option is to ask AWS to create such a range. You need to open the support case about network request and AWS will take care about the rest,

Second option is to bring your own IP (BYOIP). Yes, AWS allows you to migrate your range of IPs to AWS.

See this to learn how to do it. 

2. Use AWS Global Accelerator. This service provides an entry point to the AWS private network. Using AWS private network vs using internet provides much less latency and speeds the performance of you application.

The advantage of Global Accelerator is our use case is the ability to work with ALB


Global Accelerator gets 2 static IP addresses. If you want the range of IPs, there is no option to get such a range from AWS, But you can get it from BYOIP. If this case you still need to bring the IP to AWS following the link I provided above and choose to use them, when you are about to create the Global Accelerator.



The architecture diagram looks almost the same



Sunday, 10 April 2022

Hands Dirty with CloudWatch RUM and Global Accelerator

 From AWS official documentation...

"With CloudWatch RUM, you can perform real user monitoring to collect and view client-side data about your web application performance from actual user sessions in near real time. The data that you can visualize and analyze includes page load times, client-side errors, and user behavior. When you view this data, you can see it all aggregated together and also see breakdowns by the browsers and devices that your customers use."

So I decided to "play" with it a little bit and share my experience with you.
First of all I created new EC2 instance with Apache and placed it behind Application Load Balancer


I am not going to describe how to create EC2 with Apache and Load Balancer. There is literally tons of material how to create it. 
The client will access the Apache web server. Inside this web service I will place 2 simple pages "index.html" and "page.html". The actually interaction with "CloudWatch" is done by JavaScript which is embedded to each page. 
How do you generate this JavaScript?
Go to "CloudWatch RUM" page.





and click "Add App monitor"

For this basic example all you need is to enter the monitor name and the domain name of your Application Load Balancer 


and click 

After the monitor is created go to the list view of monitors and click on the "View JavaScript"


This is the javascript you need to embed to each page in your application.

As I mentioned I created 2 pages. (I changed the GUID and AWS account number for the security reason)
index.html
<html> <head> <script>(function(n,i,v,r,s,c,x,z){x=window.AwsRumClient={q:[],n:n,i:i,v:v,r:r,c:c};window[n]=function(c,p){x.q.push({c:c,p:p});};z=document.createElement('script');z.async=true;z.src=s;document.head.insertBefore(z,document.head.getElementsByTagName('script')[0]);})('cwr','3XXXXXXXXXX-bcd6-560ac0152ba0','1.0.0','eu-central-1','https://client.rum.us-east-1.amazonaws.com/1.2.1/cwr.js',{sessionSampleRate:1,guestRoleArn:"arn:aws:iam::66666666666:role/RUM-Monitor-eu-central-1-621094298987-6633853759461-Unauth",identityPoolId:"eu-central-1:fc86651c-d9c1-4387-8a3a-99e23dd77fec",endpoint:"https://dataplane.rum.eu-central-1.amazonaws.com",telemetries:["performance","errors","http"],allowCookies:true,enableXRay:false});</script> </head> <body> Hello from index.html <a href="page.html">Go to page.html</a> </body> </html>

and "page.html"

<html> <head> <script>(function(n,i,v,r,s,c,x,z){x=window.AwsRumClient={q:[],n:n,i:i,v:v,r:r,c:c};window[n]=function(c,p){x.q.push({c:c,p:p});};z=document.createElement('script');z.async=true;z.src=s;document.head.insertBefore(z,document.head.getElementsByTagName('script')[0]);})('cwr','3XXXXXXXXXX-c7a6-4be9-bcd6-560ac0152ba0','1.0.0','eu-central-1','https://client.rum.us-east-1.amazonaws.com/1.2.1/cwr.js',{sessionSampleRate:1,guestRoleArn:"arn:aws:iam::66666666666:role/RUM-Monitor-eu-central-1-621094298987-6633853759461-Unauth",identityPoolId:"eu-central-1:fc86651c-d9c1-4387-8a3a-99e23dd77fec",endpoint:"https://dataplane.rum.eu-central-1.amazonaws.com",telemetries:["performance","errors","http"],allowCookies:true,enableXRay:false});</script> </head> <body> Hello from page.html <a href="index.html">Go to index.html</a> </body> </html>


Next step, enter the index.html and start clicking 

page.html
index.html



So I clicked about 20-30 times and here is the statistics.






Conclusion. The feature is working as expected. The statistic is presented in a friendly and accurate way.

Nice. But let us investigate it more. Lets connect out Application Load Balancer to Global Accelerator and check is we see the difference.

In order to monitor the change, you need to repeat the settings above and create new app monitor, this time you need to specify "Global Accelerator" domain name in the "Application Domain" field and update JavaScript in index.html and page.html

I did all those steps and here is the statistics I got



The initial connection with Global Accelerator is 1.1ms and without 1.4ms. The rest of the data is less interesting since it is related to my workstation performance. Also, the difference may seem to be very small, but also need to remember that the application is extremely simple. 

Consultation.... I provided very simple example of the "Cloud Watch RUM". It has an ability to provide insight into  "Load Performance Impact", "Runtime Impact" and "Network Impact". 
There are options to collect HTTP error and also X-ray traces which are not covered in this post.