|
|
| (70 intermediate revisions by the same user not shown) |
| Line 1: |
Line 1: |
| == Overview == | | == Overview == |
|
| |
|
| Instructions on installing and maintaining SSL for AWS Elastic Beanstalk web apps. | | Instructions on how to install security certificates for websites hosted in AWS Elastic Beanstalk environments. |
|
| |
|
| Amazon offers its own security certificates for load balanced EC2 instances, but not for smaller stand-alone instances.
| | == AWS Certificate Manager == |
|
| |
|
| [https://letsencrypt.org/ Let's Encrypt] offers free security certificates.
| | * In the AWS management console, go to '''AWS Certificate Manager (ACM)''' |
| | * Click '''Request a Certificate''' |
| | ** '''Certificate Type''': "Request a public certificate" |
| | ** '''Fully qualified domain name:''' ''Enter domain name'' |
| | ** Click ''Add another name to this certificate'' to add any additional subdomains or wildcards to the certificate |
| | ** '''Select validation method:''' DNS validation |
| | ** Click '''Request''' button |
| | * The new certificate will be displayed in a list along with its associated domain name. |
|
| |
|
| The instructions for installing Let's Encrypt change depending on the platform. E.g.
| | == Validate the certificate’s domains == |
|
| |
|
| * Amazon Linux AMI vs Amazon Linux 2
| | Each domain listed on the certificate must be validated to prove the person creating the certificate has control of the domain. |
| * nginx server vs Apache server
| |
| * Web server for python vs web server for PHP.
| |
|
| |
|
| It is important to determine which platform is needed, what its limitations are in terms of supporting Let's Encrypt certificates before proceeding.
| | * Click on the certificate in the ACM list. |
| | * Under '''Domains''', a “Create records in Route 53” button is displayed if the Route 53 is used to manage the domain name. |
| | * Click that button. |
| | * Select the domains to validate. |
| | * Click '''Create Records'''. |
|
| |
|
| == Prerequisites ==
| | It can take up to 30 minutes for the status of the domain to change from “pending validation” to “issued.” |
|
| |
|
| All these commands are issued after using ssh to get to the command line on an Elastic Beanstalk environment.
| | == Apply the certificate to load balancers == |
|
| |
|
| * ssh access to the EBS instance
| | A certificate is used to add a "listener" to the load balancer associated with an Elastic Beanstalk instance. The listener routes HTTPS requests to the EBS instance. |
|
| |
|
| === Open port 443 (HTTPS) on the EC2 instance ===
| | * Go to the '''Elastic Beanstalk management console'''. |
| | * Select an EBS environment. |
| | * Click '''Configuration''' from the menu on the left. |
| | * Select '''Load Balancer''' > '''Edit''' |
| | * Under '''Listeners''', click '''Add Listener''' |
| | ** '''Port:''' 443 |
| | ** '''Protocol:''' HTTPS |
| | ** '''SSL Certificate:''' Select the certificate created in ACM |
| | ** '''SSL Policy:''' (blank) |
| | ** '''Default process:''' (default) |
| | ** Click '''Add''' |
|
| |
|
| * '''AWS Management Console''' > '''EC2''' > ''instance'' > click for details > '''Security Group''' > click for details
| | <span style="color:red;">Make sure to scroll down to the bottom of the page</span> to click '''Apply'''. I didn’t notice this at first and was wondering why the new listener was disappearing. |
| * '''Inbound''' tab > '''Edit''' button
| |
| * '''Add Rule''' button
| |
| ** '''Type:''' HTTPS
| |
| ** '''Protocol:''' TCP
| |
| ** '''Port Range:''' 443
| |
| ** '''Source:''' 0.0.0.0/0, ::/0
| |
|
| |
|
| Note that this can also be accomplished with a directive in an `.ebextensions` config file. See the bottom of [https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance-python.html Terminating HTTPS on EC2 Instances Running Python] in the AWS documentation for an example.
| | == Notes == |
| | === See Also === |
|
| |
|
| === Enable SSL on EC2 instance ===
| | * Legacy page: [[Installing Lets Encrypt Security Certificates In Elastic Beanstalk Environments]] |
|
| |
|
| The Amazon documentation instructs you to install `mod_ssl` with the following command which should create a file `/etc/httpd/conf.d/ssl.conf` when it completes.
| | === References === |
| | |
| <syntaxhighlight lang="sh">
| |
| $ sudo yum install mod_ssl
| |
| </syntaxhighlight>
| |
| | |
| This did not work for me for `dbarchowsky.com` which was on a t1.micro instance, Amazon Linux AMI version 2018.03. What worked instead was:
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ sudo yum install mod24_ssl
| |
| </syntaxhighlight>
| |
| | |
| These commands don't need to be entered manually. Instead they should be put into an `.ebextensions` config file so that the site can be deployed without manual configuration.
| |
| | |
| <syntaxhighlight lang="yaml">
| |
| packages:
| |
| yum:
| |
| mod_ssl : []
| |
| </syntaxhighlight>
| |
| | |
| There are (at least) two major types of EBS platforms Amazon Linux AMI vs Amazon Linux or Amazon Linux 2. The library is `mod_ssl` on Amazon Linux 2 and `mod24_ssl` on Amazon Linux AMI. PHP platform options in EBS seem to be Amazon Linux 2.
| |
| | |
| * TODO: Confirm that PHP is limited to that platform.
| |
| * TODO: Confirm if Python is limited to one of the platforms.
| |
| | |
| === Installing Let's Encrypt ===
| |
| | |
| Install Let's encrypt into `/opt/letsencrypt` with git
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
| |
| </syntaxhighlight>
| |
| | |
| == Installing certificates ==
| |
| | |
| === PHP ===
| |
| | |
| Use Let's Encrypt to install security certificates. <ref>[https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/SSL-on-an-instance.html Tutorial: Configure Apache Web Server on Amazon Linux 2 to Use SSL/TLS] - AWS documentation</ref> <ref>[https://medium.com/@gnowland/deploying-lets-encrypt-on-an-amazon-linux-ami-ec2-instance-f8e2e8f4fc1f Deploying Let's Encrype on An Amazon Linux AMI EC2 Instance] - Medium.com</ref>
| |
| | |
| The source instructions gave this command:
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ /opt/letsencrypt/letsencrypt-auto --debug
| |
| </syntaxhighlight>
| |
| | |
| But that returned the following error:
| |
| | |
| <pre>
| |
| PluginError: Unable to find a virtual host listening on port 80 which is currently needed for Certbot to prove to the CA that you control your domain. Please add a virtual host for port 80.
| |
| </pre>
| |
| | |
| This is caused by not having the typical [https://httpd.apache.org/docs/2.4/mod/core.html#virtualhost VirtualHost running on port 80] in the Apache configuration, so Certbot needs an alternative method for authenticating the doamin. It's possible to manually specify the web root of the website: <ref>[https://community.letsencrypt.org/t/error-installing-lets-encrypt-on-aws-linux/52227/3 Error installing Let's Encrypt on AWS Linux] - AWS forums</ref> (Set `/var/www/webroot` to a path appropriate to the environment.)
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ /opt/letsencrypt/letsencrypt-auto --debug --authenticator webroot --installer apache -w /var/www/webroot -d mydomain.com -d www.mydomain.com
| |
| </syntaxhighlight>
| |
| | |
| <div class="alert alert-warning">Note that the path to webroot can be different from the example above, e.g. `/var/www/html`</div>
| |
| | |
| ==== Preserving Let's Encrypt configuration ====
| |
| | |
| Create a configuration file at `/etc/letsencrypt/config.ini`.
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ echo "rsa-key-size = 4096" >> /etc/letsencrypt/config.ini
| |
| $ echo "email = ________@____.com" >> /etc/letsencrypt/config.ini
| |
| </syntaxhighlight>
| |
| | |
| === Python ===
| |
| | |
| [https://blog.lucasferreira.org/howto/2017/07/21/set-up-let-s-encrypt-ssl-certificate-with-aws-elastic-beanstalk-single-instance.html Set Up Let's Encrypt SSL Certificate With AWS Elastic Beanstalk Single Instance] has good clear instructions on how to accomplish this. Also see [https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance-python.html Terminating HTTPS on EC2 Instances Running Python] in the AWS documentation, which is the basis for that blog post.
| |
| | |
| Create a config file in `.ebextensions` for SSL and use `eb deploy` to update the environment (this should also work for PHP environments).
| |
| | |
| With this method the domain names and admin email address are specified with environment variables. This is nice because staging and production can have different secure domain names while sharing the same code base.
| |
| | |
| To set the values for these variables: '''AWS Management Console''' > '''Elastic Beanstalk''' > ''choose application'' > ''choose environment'' > '''Configuration''' > '''Software''' > '''Modify'''
| |
| | |
| * `LE_DOMAIN_ARGS` - List of all domains to be included in the certificate. Each domain name should be preceded by the `-d` flag, e.g. `-d mydomain.com -d www.mydomain.com`
| |
| * `LETSENCRYPT_DOMAIN` - Primary domain for the purposes of creating a symlink between /etc/letsencrypt/live/ebcert/ and the directory where Let's Encrypt actually places the certificate files.
| |
| * `LETSENCRYPT_EMAIL` - Contact email
| |
| | |
| Reference the [https://github.com/dbarchowsky/north-rose north-rose] project for a working example of this configuration.
| |
| | |
| ==== Troubleshooting ====
| |
| | |
| The AWS documentation assumes that you generate the certificates manually and insert the contents of the certificate in the `.ebextensions` config file. The alternative example above places the command to generate the certificates in the `.ebextensions` config file. There is a flag that is incompatible with production environments: `--staging`. This will cause the Let's Encrypt staging server to issue the certificates. The server address will also get stored in a local config file, so subsequent attempts to reissue the certificates without the `--staging` flag will still invoke that staging server. <ref>[https://community.letsencrypt.org/t/cn-fake-le-intermediate-x1/13437/4 CN=Fake LE Intermediate X1] - Let's Encrypt forums</ref>
| |
| | |
| One symptom of this situation are testing the domain's SSL with [https://www.digicert.com/help/ digicert] will result in a report stating that "Certificate Name matches domaininquestion.com", however the issuer will be listed as "Fake LE Intermediate X1". A valid production certificate will have "Let's Encrypt Authority X3" as the issuer.
| |
| | |
| Another symptom is that the browser will state that the domain's certificate is not from a trusted source, even though everything will look as expected in the `ssl.conf` file and in `/etc/letsencrypt/live/ebcert/`.
| |
| | |
| == Renewing certificates ==
| |
| | |
| === Cron job ===
| |
| | |
| Let's Encrypt certificates expire every 90 days. Create a cron job (in `/etc/crontab`) that will run once per day to check and renew the certificates as necessary.
| |
| | |
| Follow the renewal of the certificate with a restart of the Apache server in order to have the server recognize any renewed certificates.
| |
| | |
| <pre>
| |
| # Renew SSL Certs
| |
| 0 1 * * * ec2-user /opt/letsencrypt/letsencrypt-auto --no-bootstrap renew
| |
| | |
| # Refresh Server
| |
| 10 1 * * * root apachectl -k restart > /dev/null 2>&1
| |
| </pre>
| |
| | |
| === Manually ===
| |
| | |
| Certificates can be manually forced to renew with
| |
| | |
| <syntaxhighlight lang="sh">
| |
| $ /opt/letsencrypt/certbot-auto renew --force-renewal
| |
| </syntaxhighlight>
| |
| | |
| == Troubleshooting ==
| |
| | |
| === URLs for evaluating a domain's SSL ===
| |
| | |
| * [https://www.ssllabs.com/ssltest/analyze.html Qualys SSL Labs]
| |
| * [https://www.sslshopper.com/ssl-checker.html SSL Shopper]
| |
| * [https://www.htbridge.com/ssl/ High-Tech Bridge]
| |
| * [https://www.digicert.com/help/ digicert]
| |
| | |
| === systemctl command not found ===
| |
| | |
| The AWS documentation uses `systemctl` to restart the Apache server. If this command is not available use the `service` command instead.
| |
| | |
| === Cannot find SSLCertificateFile directive ===
| |
| | |
| When running `letsencrypt-auto` or `certbot-auto`
| |
| | |
| <pre>
| |
| Cannot find an SSLCertificateFile directive in /files/etc/httpd/conf/httpd-le-ssl.conf/IfModule/VirtualHost. VirtualHost was not modified
| |
| Unable to find an SSLCertificateFile directive
| |
| </pre>
| |
| | |
| This was fixed by successfully installing `mod_ssl`
| |
| | |
| === ERR_CONNECTION_REFUSED in Chrome ===
| |
| | |
| Attempting to load the site using https protocol in Chrome results in ERR_CONNECTION_REFUSED error.
| |
| | |
| This was fixed after the certificate was installed (creating the httpd-le-ssl.conf file with correct SSL directives).
| |
| | |
| === Re-installing certificates after upgrading an Elastic Beanstalk instance platform ===
| |
| | |
| When [[AWS Elastic Beanstalk#Upgrading the platform of an Elastic Beanstalk instance|updating the platform of an Elastic Beanstalk instance]] (e.g. Linux 2.0.x > Linux 2.9.x), the `/opt/letsencript/` directory is not copied over to the new EB instance.
| |
| | |
| It is necessary to go through all the installation steps for [[EC2_Security_Certificates#Prerequisites|Let's Encrypt]] and a [[EC2_Security_Certificates#Installing_certificates|new Let's Encrypt certificate]].
| |
| | |
| == Reference ==
| |
| === See also ===
| |
| | |
| * [https://letsencrypt.org/docs/integration-guide/ Let's Encrypt Integration Guide]
| |
| | |
| === Notes ===
| |
| <references /> | | <references /> |
|
| |
|
| [[Category:AWS]][[Category:Elastic Beanstalk]][[Category:Web Development]] | | [[Category:AWS]][[Category:Elastic Beanstalk]][[Category:Web Development]] |