How to add Static route after virtnetwork service started - centos7

I need to add this route after server booted and virtnetwork service started staticly
ip route add x.x.x.x/27 via 192.168.1.1 dev viifbr0

for static route:
route add 192.168.100.0 gateway 192.168.100.10 ens33
Default route:
route add 0.0.0.0 gateway 192.168.100.10 ens33

Related

How to deploy Amplify application with Express API route?

On my localhost I have frontend (Vue app on port 5000) and backend (Express app runs on port 3000) Node apps. The frontend is making requests to localhost:3000/api/v1/....
I'm trying to run the frontend and backend on the same DNS record (examle.com) - the backend will run on route example.com/api/v1/....
I managed to run the frontend on AWS amplify on the DNS (examle.com), but how do I add the backend to the same DNS record with /api/v1 route?
Is there a built in way in AWS Amplify? Maybe I need to create ALB, and allow the ALB/API GW to route the traffic?

Amazon EC2 - Listen for HTTPS request and Redirect to SpringBoot

I have a frontend React application hosted on Amazon Amplify and a backend SpringBoot application hosted on Amazon EC2.
My domain can only send https request but SpringBoot by default is http. My question is how can my EC2 instance listen to HTTPS request and then redirect to http port in SpringBoot.
I checked other posts and seems like you should not add SSL to your SpringBoot application, but rather to the Load Balancer in front of it. At the end of the today, this is what I want:
POST https: xxx.xxx.xxxx:443/user/signin
---> http: xxx.xxx.xxxx:8080/user/signin
---------------------------------------- update ----------------------------------------
Marcin has provided a top level idea on how to solve this, thank you!
I also attached the step-by-step solution for people like me, please see answers below
Below is the complete steps to take to convert your
http api to https using aws ec2
disclaimer: I only researched for couple hours, some concept might be inaccurate or wrong, but following this guide does gets the job done, correct me for misleading information
(1) springboot:
keep your server port on 8080 and don't change it to https (443)
(2) make sure your EC2 instance has the correct *VPC* and *IPv4 CIDR* set up
go to Instances -> Description -> VPC ID and then click on it
you should now see the list of VPCs, find the one that associated with your instance
In detail -> IPv4 CIDR -> check if it has two or more values in below format:
xxx.xx.0.0/16
xxx.xx.0.0/16
(3) skip this step if you have two IPv4 CIDR set up
select your VPC instance -> click Actions -> EDIT CIDRS -> Add new IPv4 CIDR
make sure two IPv4 CIDR are in different zone
more information on IPv4 CIDR:
https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html
(4) now we want to create an application load balancer that listens to https:443 request
select HTTP HTTPS Application Balancer and for each step (as shown in aws)
step 1.
Load Balancer Protocol and Port: https: 443
step 1.
Availability Zones: now is the time to select your VPC and two zones
step 2.
Security Setting choose a certificate from ACM (assume you have one on Route 53)
step 3.
Security Group: make sure to select the same group as your EC2 instance
step 4.
Routing http: 8080, target type: instance
step 5.
Register Targets select your EC2 instance, on port 80, please don't forget!
(5) now load balancer set up, double check security group of your EC2 instance
go to instances -> Description -> Security Group and click on it
for inbound rule, keep port 443, 22, 80, 8080 don't remove 8080
443 is for https, 22 for ssh client, 80 for tomcat
(6) now find the ips to use for the https request
this is not the public ip address of your EC2 instance
your application is behind a load balancer, the ip address should be the network interface IP. each network interface IP associates with a subnet ID that your VPC uses.
so go to Network Interfaces in your EC2 console. select any of your network interface IDs with a subnetId under your EC2's VPC.
click Details -> and scroll down to find the public IP you need
(7) before start next step, make sure you have the following:
a domain hosted in Route 53 (I have one for my frontend UI)
SSL certificated got from aws Certificate Manager
you should have put this SSL to your load balancer in step 3
if don't know what to do, check this stackOverFlow post for answers:
Adding SSL to domain hosted on route 53 AWS
(8) before next step, make sure you understand the following:
If you directly test your https request in postman, you will likely succeed.
However you will fail if using in production, like this:
axios.get("https:xxx.xxx.xxx:443/user/signin");
(failed)net:ERR_CERT_COMMON_NAME_INVALID
This is because whatever static IP you are using, does not match the AName for your SSL certificate. For example, if your domain name is helloworld.com, your backend API request should be https://helloworld.com/user/signin
(9) create a subdomain and config it in Route 53
I'm getting lazy, please see the link below:
https://aws.amazon.com/premiumsupport/knowledge-center/create-subdomain-route-53/
(10) final step!!!!!!
Now you have a working subdomain, let's use it for your network interface IP
For test, you can pick any IP from the list of network interface IPs. Go to Route 53 -> Hosted Zones -> select your subdomain, example: api.helloworld.com -> create record
Record Format
name: api.helloworld.com
type: A
Routing: Simple
Value: <your_network_interface_ip_address_multiple>
(11) sorry not yet ready
please wait for couple of days for DNS record to be updated, if DNS can interpret your subdomain, let's say api.helloworld.com into your network interface IP and since you can already test the correctness of your IP in postman, you should be ready to go!
--------------------------- end of useful information ---------------------------
If you want to keep using only the instance (no load balancer or cloudfront), then you need to get your own domain for it. Then you have to register a valid, public SSL certificate for that using, e.g. letsencyrpt. Once you have that, you can setup nginx on the instance to accept the https connections, and forward to your spring boot as http.
The easier route is to use application load balancer. You still need your own domain, but once you have it, you can easly get free SSL cert from AWS ACM and then deploy it on the balancer. No need to change your instance. So it would be:
Client ---(HTTPS)---> ALB ---(HTTP)---> EC2

Can I define subdomains for a classic AWS ELB that was provisioned by Istio?

I deployed Istio in a Kubernetes cluster hosted in AWS EKS. That created a Kubernetes service of type LoadBalancer named istio-ingressgateway with an external hostname of [redacted]-redacted.us-west-2.elb.amazonaws.com, and automatically provisioned an AWS ELB, type classic. That's great. (Note: in AWS console I do not see a hosted zone for this elb hostname, it doesn't look like I can configure aliases or whatnot)
I've been able to connect a gRPC client running outside the cluster, to a gRPC server running in the cluster by defining an istio gateway which opens port 80 to host:"*", and defining an istio virtual service which routes port 80 to my destination (some port of some kubernetes service). So far so good.
Now I would like to do this for a second gRPC endpoint in the cluster. As far as I know, my choices are: either route by opening a second port (say 81) on the ingress (which I'm choosing not to do for now). Or route by defining subdomains of [redacted]-redacted.us-west-2.elb.amazonaws.com, or route by implementing "virtual hosting", i.e. two services on the same domain where the client sends host:"svc1" in a header.
This is where I'm stuck. I don't know how do define subdomains to this ELB domain name, and I don't know if I can do virtual hosting with TLS, and if so, can I still use the "passthrough" tls mode of Istio so as not to TLS-terminate on the gateway.
1- Using subdomains: When on my developer machine I try getent hosts svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com it does not map to an IP, whereas if remove the svc1 prefix DNS returns 3 IPs (guessing the 3 availability zones in us-west-2). So I can't prefix svc1 to the domain without some work.
Can I define subdomains svc1 and svc2 for a domain created by classic AWS ELB automatically provisioned by deploying Istio, and if so how? Can I do this with kubectl/istioctl to configure Istio, or do I need to do this with the AWS CLI? Can this be done without registering a domain, i'm fine with that user-unfriendly elb.amazonaws.com hostname?
2- Virtual Hosting: Alternatively I could add a host=svc1 in the gRPC metadata. I tried adding ctx := metadata.AppendToOutgoingContext(context.Background(), "Host", "svc1") to my Go client, that did not work.
Some guidance would be great.
Update 1, and one solution for plaintext
I'm reading on List of HTTP header fields the "Host" header should not be used in HTTP2. Given this is gRPC it is HTTP2 and as such I should not add this as a custom header in my gRPC client requests. The solution when doing virtual hosting, in a gRPC client instead of sending a "host" header, you send an ":Authority" header, the value must correspond to the host specified in istio's gateway+virtualservice. This works for me. In my Go client I had to add dialOptions = append(dialOptions, grpc.WithAuthority("[my-service-1]")).
That solution won't work for TLS according to GoDoc grpc.WithAuthority. So I still need to find how to route 2 services from the same external IP and port when TLS is used.
Update 1.1:
In virtual hosting, when TLS is used, the SNI can be passed in the CLIENT HELLO message, instead of being a gRPC header like in plaintext . Depending on your language the exact API is going to vary, but in Go I was able to pass the host name by setting the ServerName field in tls.Config. You can then gate on that hostname in your istio gateway configuration, and route based on that value in your istio virtualservice.
Update 2: I tried, and failed, to create the subdomain on AWS Route53. First I create a public hosted zone for domain:[redacted]-redacted.us-west-2.elb.amazonaws.com. Next, in that hosted zone I create an A record with name=svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com, route=Alias to Classic Load Balancer, region=us-west-2, load balancer=dualstack.[redacted]-redacted.us-west-2.elb.amazonaws.com.
I later test the svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com A record exists with dig, which does not return an answer. However dig does return 3 A records for [redacted]-redacted.us-west-2.elb.amazonaws.com (without the svc1 prefix),with the IPs of 3 load balancers.
Istio
Can I define subdomains svc1 and svc2 for a domain created by classic AWS ELB automatically provisioned by deploying Istio, and if so how?
You can't do it with istio, you have to configure that in the cloud, in your case you have to configure that on aws.
On istio you can only specify the hosts, which would be the subdomains configured on aws.
Virtual Services would look like this:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mipnw-vs1
spec:
hosts:
- svc1.example.com
http:
- name: "svc1-route"
match:
- uri:
prefix: /
route:
- destination:
host: svc1.default.svc.cluster.local
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mipnw-vs2
spec:
hosts:
- svc2.example.com
http:
- name: "svc2-route"
match:
- uri:
prefix: /
route:
- destination:
host: svc2.default.svc.cluster.local
Aws
I would love to learn how to create 2 subdomains "abc" and "def" for domain "[redacted]-[redacted].us-west-2.elb.amazonaws.com"
I'm not exactly sure that's what you're looking for, but I did some research in the aws documentation and I found that you could use Amazon Route 53 to achieve what you need.
Amazon Route 53 is a highly available and scalable cloud Domain Name System (DNS) web service. It is designed to give developers and businesses an extremely reliable and cost effective way to route end users to Internet applications by translating names like www.example.com into the numeric IP addresses like 192.0.2.1
The following informations are collected from:
https://aws.amazon.com/route53/faqs/
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-elb-load-balancer.html
If you host a website on multiple Amazon EC2 instances, you can distribute traffic to your website across the instances by using an Elastic Load Balancing (ELB) load balancer. The ELB service automatically scales the load balancer as traffic to your website changes over time. The load balancer also can monitor the health of its registered instances and route domain traffic only to healthy instances.
To route domain traffic to an ELB load balancer, use Amazon Route 53 to create an alias record that points to your load balancer. An alias record is a Route 53 extension to DNS. It's similar to a CNAME record, but you can create an alias record both for the root domain, such as example.com, and for subdomains, such as www.example.com. (You can create CNAME records only for subdomains.)
Amazon Route 53 also offers alias records, which are an Amazon Route 53-specific extension to DNS. You can create alias records to route traffic to selected AWS resources, including Amazon Elastic Load Balancing load balancers, Amazon CloudFront distributions, AWS Elastic Beanstalk environments, API Gateways, VPC interface endpoints, and Amazon S3 buckets that are configured as websites. Alias record typically have a type of A or AAAA, but they work like a CNAME record. Using an alias record, you can map your record name (example.com) to the DNS name for an AWS resource(elb1234.elb.amazonaws.com). Resolvers see the A or AAAA record and the IP address of the AWS resource.
And there is Question about the subdomains
Can I use 'Alias' records with my sub-domains?
Yes. You can also use Alias records to map your sub-domains (www.example.com, pictures.example.com, etc.) to your ELB load balancers, CloudFront distributions, or S3 website buckets.
Additional resources:
https://medium.com/cloud-native-the-gathering/istio-ingress-to-expose-your-k8s-services-via-individual-dns-2ec9c2717b81
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-routing-traffic-for-subdomains.html

In AWS - Subdomain with SSL Certificate doesn't work in RESTful call

I have an AWS Amplify instance to launch a REACT app I have. It also has an SSL Certificate, so I can access the app on the browser by entering:
https://myreactapp.com (not my real app url, just an example)
I have a web servlet running on an Elastic Beanstalk instance that doesn't have SSL certificate, and my REACT app interfaces to it with this code snippet I have:
var myObject = {
data1: this.state.data1,
data2: this.state.data2
}
$.ajax({
type: "POST",
url: 'http://<my-backend-webservices-app>.us-east-1.elasticbeanstalk.com/doSomething', // works only from React app when running on local machine (http://localhost:3000), not from https url
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
data: myObject,
success: function(response) {
console.log('success -- ' + response);
},
function(errMsg) {
alert('Major Error');
}
});
This code works fine and I get a response from my my-backend-webservices-app when I run my React App locally on my machine. Since when I use it locally the react app is on http://localhost:3000 (notice its not an https) and its talking to the Elastic Beanstalk instance which is also on http.
But when I run my React app from the AWS Amplify with SSL certificate it complains that a RESTFul request from HTTPS can't communicate to http url. Here's the error from the browser:
jquery.js:8676 Mixed Content: The page at
'https://master.<.....>.amplify<...>.com/' was loaded over HTTPS,
but requested an insecure XMLHttpRequest endpoint
'http://.us-east-1.elasticbeanstalk.com/doSomething'.
This request has been blocked; the content must be served over HTTPS.
So my thought to resolve this is to add a SSL Certificate to my ElasticBeanStalk instance. So first I created a subdomain services.myreactapp.com where the main domain is myreactapp.com I then assigned my ElasticBeanstalk instance (where my my-backend-webservices-app is) to that services.myreactapp.com subdomain.
I then went to the Certificate Manager service page of aws and requested a public certificate that is assigned to the services.myreactapp.com subdomain.
So now I updated the URL of the code snippet above to have https instead of http:
url: 'https://<my-backend-webservices-app>.us-east-1.elasticbeanstalk.com/doSomething',
But now whenever my React app from https makes the request to the back end servlet, it just hangs.
Any thoughts at what I'm missing?
Few things to highlight here.
about ACM issued Certificates
First of all, if you request a certificate from the certificate manager, it won't be applied to any of your applications automatically, you need to apply the certificate to your applications.
using ACM issued Certificate with Elasticbeanstalk
You can apply the certificate obtained from ACM to the elasticbeanstalk only if you are using a load balancer. In this case You can simply select your certificate from your elasticbeanstalk configuration page.
Reference:
configure ssl for elasticbeanstalk load balancer - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-elb.html
If you are not using load balancer (Single instance)
You have to apply the certificate to the application running inside elasticbeanstalk or its proxy (for e.g nginx). You can use .ebextensions to achieve this.
Reference:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance-nodejs.html
https://medium.com/#hzburki.hzb/configure-ssl-certificate-elastic-beanstalk-single-instance-a2846211851b
Pointing subdomain.example.com to elasticbeanstalk's DNS name
Once you have enabled SSL on your loadbalancer or configured your single instance to serve your application over ssl, you can create an A record to point services.myreactapp.com to your elasticbeanstalk dns name. make sure to to select Alias Yes when you create the A record.
Using the new dns name from your frontend app
finally you can use subdomain.mydomain.com from your frontend app instead of the elasticbeanstalk dns name.
Hope this helps, good luck.
I was able to get it working thanks to https://stackoverflow.com/a/59540740/4722577 #Arun K's response above.
The link I used was:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-elb.html
In short, through the Configuration -> Load Balancer -> Modify button I had to configure my Elastic Beanstalk EC2 instance to use Load Balancing with a listener. Then associate the existing SSL Certificate I have with this listener.
However, when I tried to do that at first that modify button didn't exist (notice it says that Load balancing is not available in my configuration).
Part of the aws link mentions this if you get that message:
Note If the Load balancer configuration category doesn't have a Modify
button, your environment doesn't have a load balancer.
The way forward is to select Configuration -> Capacity -> Modify on the screenshot above, then select "Load Balanced" instead of "Single Instance" in the Environment Type drop down box.
After you apply those changes, a "modify" button is enabled for Configuration -> Load Balancer sub panel. I continued the steps in the AWS link above and am now able to communicate from my https://myreactapp.com to my my-backend-webservices-app
Go to AWS route 53, In DNS management create a CNAM DNS record which points to your beanstalk url, like -
services.myreactapp.com -> xyz.us-east-1.elasticbeanstalk.com
then use services.myreactapp.com in your react app as url. Also before doing that make sure that you are able to access your backend at https://services.myreactapp.com, you can check you health API if any to test that. Note - This might take sometime to get services.myreactapp.com to come in action.

Route 53 URL Forwarding to Elastic Load Balancer

I got a record set in Route 53 redirected from api.domain.com to a load balancer for component X.
Now I got multiple components so I want to be able to do api.domain/auth which redirects to the auth load balancer. How would I configure this in Route 53 and is this even possible?
/auth is the path component of an HTTP URL. Route53 is a DNS service that has no awareness of the application layer. You cannot use Route53 to handle this redirect. A few other options to accomplish this:
Point api.domain.com to an Apache httpd or Nginx service that can perform path-based routing
Use the new AWS API Gateway Service to perform the routing. You'd point api.domain.com at your API Gateway URL, then set up methods in the API gateway to route /auth to the appropriate service