Where does AWS Elastic Beanstalk Load Balancer look for certifications? - amazon-web-services

I am setting up AWS Elastic Beanstalk application and I want the traffic to it to be HTTPS.
I created a DNS CNAME record matching the beanstalk url and created and approved a certificate for that DNS name in AWS Certificate Manager.
Now I went to Elastic Beanstalk environment --> Configuration --> Network Tier / Load Balancer (Image below) in order to set the "Secure listener port" from OFF to 443 and choose my certificate.
But my certificate is not there to choose from !
So My question is how to get my certificate or a certificate into that selection list, or is that a bug in AWS?
Note - I was able to see my certificate when going to EC2 / Load balancers and was able to change the load balancer from HTTP to HTTPS and choose my certificate there.
But this did not reflect on Elastic Beanstalk load balancer configuration that still shows port 80. Using HTTPS to the beanstalk did not work this way.
Help!

Through the console, there is currently no way to assign your certificate you created in the Certificate Manager to your Beanstalk environment.
In order to accomplish this, you will need to use the AWS CLI. I was able to accomplish this, and luckily, it is easy.
In short, you need to:
create a elb-acm.json file and place it somewhere in your web root. I put mind directly in the web root of my application.
go to the Certificate Manager and get the arn ID of your certificate
use the update environment command to apply your certificate to your environment
aws elasticbeanstalk update-environment --environment-name Your-Environment --option-settings file://PATH-TO-JSON/elb-acm.json
For me the path was simply file://elb-ecm.json since (I believe the reason is because) I was running the command while in the web root and the file was in that same directory This article goes into detail (and worked for me). Good luck!
Please note, though you can, you should NOT assign the certificate directly through the Load Balancer console (EC2 > Load Balancers) because the load balancer will be blown away and recreated whenever you rebuild your Beanstalk Environment.
Also, make sure you have setup your certificate how you want it before you apply it to your Beanstalk environment. For example, if you want *.mydomain.com and the naked mydomain.com to both be secure, make sure that's fully configured first since there is no easy way to "de-associate" your certificate from your environment once your run these commands (you would basically need to terminate your environment altogether and create a new one if I'm not mistaken in this scenario).
Also, you will want to have some redirect code in your app to perform a 301 redirect on any non-secure request coming in once you have your certificate setup. To perform the redirect you will need to look for the X-Forwarded-Proto header on the incoming request. If it's not secure, you should redirect to the secure port. For example, here is how my application code looks:
// in production, only allow secure requests (https)
public function performSecureRedirect(rc) {
// based on domain comparison
var isLive = myEnvironmentData.isLive;
// setting up the health check url is important for smooth beanstalk deployments
// beanstalk issues this healthcheck request via a non-secure port
var isAmazonHealthcheckUrl = rc.event eq "system.healthcheck";
if (isLive and not isAmazonHealthcheckUrl) {
var headerData = getHTTPRequestData().headers;
// x-forwarded-proto is a special header
// setup by Amazon ELB (Elastic Load Balancer)
var requestProtocol = getHttpRequestData().headers['x-forwarded-proto'];
var isSecureRequest = requestProtocol eq "https";
if (not isSecureRequest) {
location("https://" & cgi.server_name & cgi.path_info, false, 301);
}
}
}

The answer by Brian FitzGerald and this blog helped me figure out a simple way to do that (set https on the Elastic beanstalk load balancer and use a CRM certificate for it).
The solution is simpler using AWS Elastic Beanstalk CLI (eb for short). After you set up the environment properly you can use eb config command.
When the edit window opens up scroll down to aws:elb:loadbalancer section.
Modify the load balancer section to be so (in my case I removed port 80 altogether, you may want to keep it):
aws:elb:loadbalancer:
CrossZone: 'true'
LoadBalancerHTTPPort: 'OFF'
LoadBalancerHTTPSPort: '443'
LoadBalancerPortProtocol: HTTP
LoadBalancerSSLPortProtocol: HTTPS
SSLCertificateId: PLACE HERE THE CRM CERTIFICATE ARN
SecurityGroups: '{"Fn::GetAtt":["AWSEBLoadBalancerSecurityGroup","GroupId"]},{"Ref":"AWSEBLoadBalancerSecurityGroup"}'
The arn of the certificate can be found in AWS > Certificate Manager.
Open the certificate and copy the ARN number (on the bottom right).
I saved the configuration, waited for the environment to get updated and that was it.

Related

Allowing https for Elastic Beanstalk

I'm about to lose my mind trying to set this up. I have lost the whole day and can't seem to get near what I want to do.
I have a node js rest api uploaded trough elastic beanstalk, and I'm trying to setup a webpage to present the api, but for the live example to work the api needs to be accessed trough https. I've read the instructions for setting up the https for elastic beanstalk (and like everything on the AWS documentation it is a ridiculous maze). It has sent me trough several different AWS services.
What I basically got from it so far is that I need to set up a Load Balancer that will receive the connection trough https and forward the user to my instance. But I can't get it to work. I have a domain from freenom: bibliaparahumanos.tk, it is setup with an A alias to my EC2 IP, and it works with http, but if I try to access it trough https, I get "connection refused". If I use my normal Elastic Beanstalk url (http://apibibliahumana-env.eba-3nbmrphf.us-east-2.elasticbeanstalk.com/) with https it works, but I get a warning that the connection is not secure due to the domain on the certificate being different from the domain I'm accessing (which I understand, since the domain in the certificate is for my freenom domain).
I have the Load Balancer Listener set up with:
Protocol: https
Port: 443
Default action: forward to target group
(I have tried the target group with both http and https and the problem remains).
My certificate is from AWS Certificate Manager.
I have also seem this other tutorial but it confused me more. It adds some steps for configuring stuff on the app bundle, but I don't understand if it's required or an alternate way. I have tried setting that up, but it asks me to add the certificate's public key, which I can't figure out how to find.
I would suggest adding a CNAME record to your DNS towards apibibliahumana-env.eba-3nbmrphf.us-east-2.elasticbeanstalk.com.
A big advantage of using elastic beanstalk is that you can do blue/green deployments; as you will instead add the app URL to your DNS you can build an entire new environment in elastic beanstalk, test/wait until its stable and swap the app urls; which results in deployments without any downtime.
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.CNAMESwap.html

Add SSL to web app built using aws eb cli

I built a web app on top of aws elastic beanstalk cli. I'm trying to add a SSL certificate to the site to make it more secure. The documentation says "The simplest way to use HTTPS with an Elastic Beanstalk environment is to assign a server certificate to your environment's load balancer". However, I don't see my app on the Elastic Beanstalk console although is is up and available to the public. Does anyone know how to use HTTPS with an Elastic Beanstalk environment and/or to assign a server certificate to my environment's load balancer (not sure how to access my env load balancer either).
Did you choose the right region when you logged into the console? That would be the only reason you don't see the app. Once you choose the right region, you should see your application. You can add a cert by going to the Elastic Beanstalk console ==> configurations ==> Load balancer and Add Listener, choose 443, https and the cert. Just make sure to add port 443 and open traffic on that port in the load balancer's security group. This blog post explains the process in ABC simple, step-by-step manner:
https://aws.amazon.com/premiumsupport/knowledge-center/elastic-beanstalk-https-configuration/

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.

How do I know if I am using AWS Certificate Manager correctly?

What is my indication that I am using AWS Certificate Manager correctly and that any remaining problems getting my site to load at https are due to a mistake I am making in my Apache configuration?
In AWS Certificate Manager, I see "Success! Your certificate was issued successfully." Does that mean there are no further steps for me to complete in the AWS console, and I need only get my Apache configuration correct to finish?
Currently, when I try to visit a URL at my site with the http protocol, it loads fine, but when I visit at https, the browser tries to load the page but it never loads.
I have followed the instructions for creating an HTTPS listener, but still do not know if I am done with all necessary steps in AWS console. How would I know?
Edit: To clarify, I am using an Elastic Load Balancer (ELB), since the documentation indicated I need to use ELB with AWS Certificate Manager (ACM). However, I do not know how to determine if I have configured everything correctly in AWS console that I need to in order to access the site at HTTPS.
Edit 2: This might come close to answering my question, possibly, but I don't know how to do this: "You can use curl, telnet etc from your local machine to verify 443 port status on ELB" -- #vivekyad4v.
ACM(AWS Certificate Manager) supports the AWS resources like ELB, Cloudfront, API Gateway etc. You can add SSL certificates to these
resources via AWS console.
Currently, it doesn't support EC2. You cannot use ACM with EC2 instances, you will need a Load Balancer in front of it. Once you have a load balancer, SSL termination happens on the load balancer & not on the EC2 instance.
Once it is setup, you can change your apache server config to redirect all HTTP requests to HTTPS.
Add certificate to ELB - "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-update-ssl-cert.html"
Update apache config - "https://aws.amazon.com/premiumsupport/knowledge-center/redirect-http-https-elb/"
No EC2 support - "https://aws.amazon.com/certificate-manager/faqs/"

AWS Elastic Beanstalk Namecheap SSL Configuration

My iOS software platform runs on AWS Elastic Beanstalk and has a URL we'll call "something.elasticbeanstalk.com". I have a website we'll call "website.com" I purchased and operate the DNS records for through Namecheap. I need to make the URL my iOS client apps use to connect to the server HTTPS since Apple is requiring this soon due to App Transport Security.
WHAT I THINK I'M SUPPOSED TO DO
What I think I'm supposed to do is, create an SSL certificate for "website.com" and apply that SSL certificate to the AWS EB load balancer. Then I need to create a subdomain for "website.com" that redirects traffic to "something.elasticbeanstalk.com". Client apps connect to the subdomain of "website.com" which is now HTTPS and redirects to "something.elsastic.beanstalk.com". Is that correct?
WHAT I'VE DONE SO FAR
So far, I created a SSL certificate for "website.com" using AWS Certificate Manager. For this I had to verify my email address associated with "website.com". I then applied that SSL certificate to my environment's load balancer int the AWS Management Console. After that, I went into Namecheap and followed this guide in the 'Domain Name & AWS 53 Management' section to do it.
I read in this article that I needed to create an alias and/or set up Nameservers in AWS Route53. I tried doing that but don't know what I'm doing and it seems to conflict with the Medium article I linked above that I followed telling me to change the CNAME record for the URL and the Redirect URL record for "website.com".
QUESTION
What do I do from here?
SITUATION
-I have a Parse Server on Elastic Beanstalk with URL “something.elasticbeanstalk.com”
-I have a domain with Namecheap called “website.com”
WHAT I NEEDED
I needed to make my client app connect to an HTTPS address since Apple is requiring it shortly with App Transport Security. Since I couldn’t get an SSL certificate using AWS certificate manager for “something.elasticbeanstalk.com”, I created one for “website.com”. I then needed to have my client app connect to the HTTPS “website.com” which would forward it over to “something.elasticbeanstalk.com”. This satisfied the HTTPS requirements of Apple.
HOW TO DO IT
Make an SSL certificate for “website.com” using AWS Certificate Manager. You will need to confirm the domain via a confirmation email to the administrator for it.
Apple the SSL certificate for “website.com” to the AWS EB Load Balancer. Go to your AWS EB Console, click "configuration", click "Load Balancing" under the "Network Tier" category. Now under the first category which is "Load Balancer", select the SSL record you made and apply it in the "SSL certificate ID" section.
Set a CNAME record for “website.com” with a host of whatever subdomain of “website.com” you want. I chose “data” as my host value and subdomain (so my subdomain is “data.website.com”). Set the value of the CNAME record to “something.elasticbeanstalk.com”. Wait for it to propagate. It’s usually pretty fast but not always.
(I’m unsure if this particular step is proper but it worked for me) Set the serverURL of Parse-Server to “https://something.elasticbeanstalk.com” and the publicServerURL to “https://data.something.com”
In the Parse “initializeWithConfiguration” method in your client app that enables the app to connect to the server, change the server URL to “https://data.something.com/parse”. NOTE: include the “/parse” which is the MOUNT PATH of the parse-server. This value MAY BE DIFFERENT for you depending on how you set it but I set it to “/parse” since that’s what I saw in the Parse-Server docs.
NOTES
-I deleted all Route53 records since they are irrelevant here since “something.com” DNS services are controlled by Namecheap.
-A Redirect URL record in Namecheap is unnecessary