AWS 3-Tier Architecture Issue - amazon-web-services

Need some serious help here, thanks a lot in advance !
I need to deploy a scalable 3 tier web application on AWS and I am having some doubts/trouble understanding the best practice to design the architecture.
NOTE: As per my understanding, all the backend requests are requested through the browser, after the Frontend server serves html/css/js to the user.
Let me show you what I have come up with till now :
Assuming the above 'note':
Cons (as per my understanding):
All the backend routes will be exposed to the outside world.
Even though backend servers are in private subnet, now that they're being accessed via external load balancer, the endpoints API could be accessed from the users.
How will we route a request from a Load balancer to another Load balancer. Because what I have seen is that you could only route a request to an EC2 instance added in the target group.
To overcome the cons as I think in the above approach, I came up with this architecture instead:
Pros (as per my understanding):
The backend routes are safe (in a way) because we have a way of internally connecting from the frontend to the backend servers(if required).
Cons:
If the request is made from the browser, the endpoints are again exposed.
Solution that I found online:
REAL BIG DOUBT IN THIS LAST ONE
This breaks all the logic of my understanding that : All the requests are made by the browser from the user to the backend because in this the requests to the backend are being routed FROM the frontend servers.
QUESTIONS
What if the backend request (say login) is made by the user from the browser?
How will this work out in such case?

seems like you have done some good work here.
Let me start by making things easy for you:
Users only interact with the Load Balancer: If you want to keep it simple and not break off your frontend asset serving to an external service like CloudFront, which you should if you are starting out, you will be hosting the application only via EC2 instances (application origin, or simply orgin). Your requests would look something like this:
Users <--> ALB <--> EC2
Notice how users never interact with EC2 instances directly, its always via Application Load Balancer (ALB).
If I can oversimply thing, this is how HTTP operates, a request is made to a resource at an IP and the response is sent back from the same resource or IP. So as in your diagram, a request will not be responded back by EC2 but rather be relayed via the ALB.
You don't need NAT gateway: NAT gateway are there to make it possible for resources in provate subnet access the internet. In this case, unless you want your application to access the internet, you don't need NAT gateway. Many large scale applications are actually locked down in part by not keeping this resource at all.
You are still protecting the origin: Given that only the ALB can be accessed over the internet and everything else internal you can structure things here in any way that you want to. you could have few internal microservices that can be used internally without ever being exposed to end users. Note that here request never leaves the VPN.
You can read more about this and build a sample application via the official docs here or access AWS tutorials here.

To me, #3 is the correct solution because it does not expose /api to end users (since you mention "I DO NOT want the users to directly access the /api"). In #1, I don't think you could limit access to /api to only the front-end servers, since security groups work on the whole load balancer, not per-target.
Also, being an Internet-facing load balancer, any requests from the front-end servers to the load balancer in #1 will be referencing the load balancer via public IP addresses. This will cause a 1c/GB charge to go "out of" the VPC and then back in again.
Only #3 correctly refers to back-end resources via private IP addresses. The internal load balancer will be referenced via private IP addresses.

Related

Reaching GCP Cloud Run instance through VPC with "only internal range" egress

The current setup is as follows:
I have a Cloud Run service, which acts as "back-end", which needs to reach external services but wants to be reached ONLY by the second Cloud Run instance. which acts as a "front-end", which needs to reach auth0 and the "back-end" and be reached by any client with a browser.
I recognize that the setup is not optimal, but I've inherited as is and we cannot migrate to another solution (maybe k8n). I'm trying to make this work with the least amount of impact on the infrastructure and, ideally, without having to touch the services themselves.
What I've tried is to restrict the ingress of the back-end service to INTERNAL and place two serverless VPC connectors (one per service), so that the front-end service would be able to reach the back-end but no one else could.
But I've encountered a huge issue: if I set the egress of the front-end all on the VPC it works, but now the front-end cannot reach auth0 and therefore the users cannot authenticate. If I place the egress as "mixed" (only internal ip ranges go through the VPC) the Google Run URL (*.run.app) is resolved not through the VPC and therefore it returns a big bad 403.
What I tried so far:
Placing a load balancer in front of the back-end service. But the serverless NEG only supports the global http load balancer and I'd need an internal one if I wanted an internal ip to resolve against
Trying to see if the VPC accessor itself MAYBE provided an internal (static) ip, but it doesn't seem so
Someone in another question suggested a "MIG as a proxy" but I haven't managed to figure that out (Can I run Cloud Run applications on a private IP (inside dedicated VPC network)?)
Fooled around with the Gateway API, but it seems that I'd have to provide a openAPI specification for the back-end, and I'm still under the delusion that this might be resolved with a cheaper (in terms of effort) approach.
So, I get that the Cloud Run instance cannot possibly have an internal IP by itself, but is there any kind of GCP product that can act as a proxy? Can someone elaborate on the "MIG as a proxy" approach (Managed Instance Group? Of what, though?), which might be the solution I'm looking for? (Sadly, I do not have the reputation needed to comment on that question or I would have).
Any kind of pointer is, as always, deeply appreciated.
You are designing this wrong. Use Cloud Run's identity-based access control instead of trying to route traffic. Google IAP (Identity Aware Proxy) will block all traffic that is not authorized.
Authenticating service-to-service

VPC SSL/HTTPS environment

I have the following VPC setup with AWS Elastic Beanstalk:
Web App Public Load Balancer pointed to by my domain (proxied through cloudflare) with EC2 instances in private subnet.
Private internal API Load Balancer with inbound access granted to EC2 instances above via Security Group
Database within the private subnet, accessible by EC2 instances behind the API Load Balancer.
I would like to enable end to end HTTPS, AWS has good documentation here (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-endtoend.html).
I have followed this, albeit with my free Cloudflare domain certs. This seemed ok until I get the following error: 'SELF_SIGNED_CERT_IN_CHAIN' when my web app tries to connect to the internal API via https://internal-aweseb-dns.amazonaws.com (DNS for internal API Load Balancer).
Questions
Is this the correct way get end to end HTTPS?; and
How do I resolve the above error? (returned by Node JS)
Thanks
In the end I came to this conclusion: I don't need end to end HTTPS when my instances are in a private subnet because:-
Once HTTPS is terminated at the Load Balancer, the internal requests are over HTTP but are not over the public internet. They requests cannot be seen by anyone outside the AWS network.
The data I am transmitting is not overly sensitive (just emails and user preferences) so there is no Compliance/Regulatory reason to enforce end to end HTTPS in a private network.
There is a small performance hit when using HTTPS as an SSL handshake must occur, which is an overhead.
I have additional security via Security Groups, only allowing internal traffic originating from the Load Balancer.
There are many suggestions that would guide you to configure your application to ignore the certificate when connecting via HTTPS... but that defeats the whole point of HTTPS (secure encrypted connection). You may as well just HTTP instead of doing this.
After much research and discussion with AWS, I think using HTTP over an internal network is secure enough for 99% of use cases and is pretty standard with a lot of setups and so unless you actually need end-to-end encryption for your use case, I would advise doing this instead.
Hope this helps.

Is HTTPS->HTTP behind load balancer considered secure?

I have a secure web API in the AWS cloud and I'm trying to figure out the best way to put it behind a load balancer without compromising security.
Right now, all communications are conventionally encrypted end-to-end. The API server has a Let's Encrypt certificate, which is used to treat all messages exchanged with clients. Unless the encryption is broken, nobody besides the server and its clients can view the raw contents of messages.
If I start using a load balancer and allow multiple instances of my server to run concurrently, I'll have to give up on LE and use centralized certificate management (e.g. ACM). AWS conveniently supports linking ACM-generated certificates to load balancer HTTPS listeners. This is especially useful for automatic renewal. However, the load balancer would then remove the encryption layer, and all communications with the instances of my server would be decrypted from that point on.
I'm not too comfortable having my raw data traveling in a public cloud. Still, I'd welcome a second opinion on this.
My question therefore is: Is it considered secure to have load balancer strip HTTPS encryption layer and forward all traffic as HTTP to internal server instances?
Since I can guess the answer, I would appreciate any suggestions on how to deploy load balancing securely.
I consider it secure because each AWS VPC is isolated from another.
The traffic of one VPC cannot be captured in another VPC. Of course whether AWS VPC technology is secure remains to be seen as others have said.
Also check out the documentation from EBS about secure end-to-end encryption. It says that:
Terminating secure connections at the load balancer and using HTTP on the backend may be sufficient for your application. Network traffic between AWS resources cannot be listened to by instances that are not part of the connection, even if they are running under the same account.

ECS container routing with an application load balancer in AWS

I know application load balancers are new in AWS, and discussions (help) are scarce up-to now.
I have a few api containers (docker) running in EC2 Container Service (ECS). I can take advantage of application load balancers to manage routing on an application level rather than a network level. This is exactly what ECS has lacked up until now.
Getting to the point...
I'm trying to get to a point where the load balancer will detect the pattern in the request url and route the request to the correct container, but route the request without the pattern included.
For example:
http://elb.eu-west-1.elb.amazonaws.com/app1/ping
Should route request '/ping' to the app1 container
http://elb.eu-west-1.elb.amazonaws.com/app2/ping
Should route request '/ping' to the app2 container
etc...
Each app has it's own target group and corresponding pattern: /app1*, /app2*
the problem
I can successfully get the a request to '/app1/ping' to route to the app1 container however the request hits the container as '/app1/ping' (obviously) but I only need '/ping' to hit the container. '/app1' is irrelevant to the container.
Any ideas how I can achieve this?
Application Load Balancers do a couple of things very well, but there's an awfull lot they do not do. This is true for a lot of AWS services (e.g. SQS just recently, after almost a decade got FIFO support) and you can either love or hate this.
Your use case seems to fit the AWS API Gateway very well, which is a service that can be used to map certain external endpoints to certain internal endpoints (and a lot more...). There's even a blog post on the AWS blog about how to use Application Load Balancing with the EC2 Container Service and the API Gateway together.

Setting up a loadbalancer behind a proxy server on Google Cloud Compute engine

I am looking to build a scalable REST webservice on the Google Cloud Compute Engine but have a couple of requirements that I am not sure how best to implement.
Structure so far:
2 Instances running a REST webservice connected to a MySQL Cloud database.
(number of instances to scale up in the future)
Load balancer to split request between the two or more Instances.
this part is fine.
What I need next is that the traffic (POST requests from instances to an external webservice) must come from a single IP address. I assume these requests can not route back through the public IP of the load balancer?
I get the impression the solution to this is to route all requests from instances though a 3rd instance running squid. Is this the best way to do this? (side question)
Now to my main question:
I have been reading about ApiAxle which sounds like a nice proxy for Web Services, giving some good access control, throttling and reporting capabilities.
Can I have an instance running ApiAxle followed by a google cloud Load Balancer which shares the request from the proxy to the backend instances that do the leg work and feed the response back through the ApiAxle proxy, thus having everything though a single IP visible to clients using the API? (letting me add new instances to the pool to add capacity.)
and Would the proxy be much of a bottle neck?
Thanks in advance.
/Dave
(new to this, so sorry if its a stupid question because I cant find anything like this on the web)
Sounds like you need to NAT on your outbound traffic so it appears to come from one IP address. You need to do that via a third instance since Google LB stack doesn't provide this. GCLB works only with inbound connections on the load-balanced IP.
You can setup source-NAT using advanced routing, or you can use a proxy as you suggested.