Configuration of SSL via Let's Encrypt for Elastic Beanstalk

Viewed 282

I want to enable SSL (using Let's Encrypt) for my Django project running on AWS Elastic Beanstalk.

tldr:
Unfortunately, it seems that when Let's encrypt connects to my website to check for the token instead it gets a 404 error.

During secondary validation: Invalid response from
   http://sub.example.com/.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI
   [107.20.106.65]: "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n
   <meta http-equiv=\"content-type\" content=\"text/html;
   charset=utf-8\">\n  <title>Page not "

Now I don't know if this problem is caused by Django configuration, nginx configuration, Elastic Beanstalk, my subdomain, Certbot or anything else...

What next steps to debug it should I take?

(Of course, the sub.example.com stands for an existing subdomain that I own.)


My domain, let's say: example.com was registered through an external domain registrar and then I created a subdomain sub.example.com which points to the EB CNAME (foo-bar-foo-bar.bar-foo.us-east-1.elasticbeanstalk.com.).

The site is available via http using both addresses (sub.example.com and foo-bar-foo-bar.bar-foo.us-east-1.elasticbeanstalk.com) and displays the Django welcome page with an image of a green rocket.

Here is the script I created to create the project and environment (following the official tutorial):

VAR_MYDOMAIN=sub.example.com
VAR_NUMBER=7
VAR_PROJECT_DIRNAME=project-foo-$VAR_NUMBER
VAR_DJANGO_PROJECT_NAME=project_foo_$VAR_NUMBER
VAR_EB_APP_NAME=project_foo_app_$VAR_NUMBER
VAR_EB_ENV_NAME=project-foo-env-$VAR_NUMBER
VAR_AWS_KEYNAME=aws_keys_name

mkdir $VAR_PROJECT_DIRNAME
cd $VAR_PROJECT_DIRNAME
py -m venv eb-virt
source eb-virt/Scripts/activate
pip install django==2.1.1
django-admin startproject $VAR_DJANGO_PROJECT_NAME
cd $VAR_DJANGO_PROJECT_NAME
pip freeze > requirements.txt
mkdir .ebextensions
echo "option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: $VAR_DJANGO_PROJECT_NAME.wsgi:application" > .ebextensions/django.config
deactivate
eb init -p python-3.7 $VAR_EB_APP_NAME -r us-east-1 -k $VAR_AWS_KEYNAME
eb create $VAR_EB_ENV_NAME
ls
sed -i -e "s|ALLOWED_HOSTS = |ALLOWED_HOSTS = \['`eb status | grep "CNAME" | cut -f 2 -d : | xargs`\',\'$VAR_MYDOMAIN\']#|g" $VAR_DJANGO_PROJECT_NAME/settings.py && eb deploy
eb open
echo "done"

Then I followed this tutorial in order to

  1. install Certbot
  2. Open port 443
  3. Configure the certificate for Nginx
  4. Add certificate renewal to cron

So I created this script:

VAR_MYDOMAIN=sub.example.com
VAR_NUMBER=7
VAR_PROJECT_DIRNAME=project-foo-$VAR_NUMBER
VAR_DJANGO_PROJECT_NAME=project_foo_$VAR_NUMBER

VAR_TEST_CERT=--test-cert
VAR_MYDOMAIN_EMAIL=validaddress@example.com

cd $VAR_PROJECT_DIRNAME/$VAR_DJANGO_PROJECT_NAME
mkdir .platform
mkdir .platform/hooks
mkdir .platform/hooks/postdeploy
echo "container_commands:
    00_download_epel:
        command: \"sudo wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/\"
        ignoreErrors: true
        test: test ! -d \"/etc/letsencrypt/\"
    10_install_epel_release:
        command: \"sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm\"
        ignoreErrors: true
        test: test ! -d \"/etc/letsencrypt/\"
    20_enable_epel:
        command: \"sudo yum-config-manager --enable epel*\"
        ignoreErrors: true
        test: test ! -d \"/etc/letsencrypt/\"
    30_install_certbot:
        command: \"sudo yum install -y certbot python3-certbot-nginx python2-certbot-nginx python-certbot-nginx\"
        ignoreErrors: true
        test: test ! -d \"/etc/letsencrypt/\"" > .ebextensions/00_install_certbot.config
echo "Resources:
    sslSecurityGroupIngress:
        Type: AWS::EC2::SecurityGroupIngress
        Properties:
            GroupId: {\"Fn::GetAtt\" : [\"AWSEBSecurityGroup\", \"GroupId\"]}
            IpProtocol: tcp
            ToPort: 443
            FromPort: 443
            CidrIp: 0.0.0.0/0" > .ebextensions/01_open_https_port.config
echo "#!/bin/sh
sudo certbot -n $VAR_TEST_CERT -d $VAR_MYDOMAIN --nginx --agree-tos --email $VAR_MYDOMAIN_EMAIL" > .platform/hooks/postdeploy/00_get_certificate.sh
echo "container_commands:
    00_permission_hook:
        command: \"chmod +x .platform/hooks/postdeploy/00_get_certificate.sh\"" > .ebextensions/02_grant_executable_rights.config
echo "files:
    /tmp/renew_cert_cron:
        mode: \"000777\"
        owner: root
        group: root
        content: |
            0 1,13 * * * certbot renew --no-self-upgrade" > .ebextensions/03_renew_ssl_certificate_cron_job.config
eb deploy
eb open

Unfortunately, during the deployment I get following errors:

Upload Complete.
2022-01-30 17:57:02    INFO    Environment update is starting.
2022-01-30 17:57:42    INFO    Deploying new version to instance(s).
2022-01-30 17:57:46    INFO    Instance deployment successfully generated a 'Procfile'.
2022-01-30 17:58:54    ERROR   Instance deployment failed. For details, see 'eb-engine.log'.
2022-01-30 17:58:57    ERROR   [Instance: i-xxxxxxxxxxxxxxxxx] Command failed on instance. Return code: 1 Output: Engine execution has encountered an error..
2022-01-30 17:58:57    INFO    Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
2022-01-30 17:58:57    ERROR   Unsuccessful command execution on instance id(s) 'i-xxxxxxxxxxxxxxxxx'. Aborting the operation.
2022-01-30 17:58:57    ERROR   Failed to deploy application.
ERROR: ServiceError - Failed to deploy application.

And in the logs I see the following information:

----------------------------------------
/var/log/eb-hooks.log
----------------------------------------
2022/01/30 17:58:18.723761 [INFO] Running command .platform/hooks/postdeploy/00_get_certificate.sh
2022/01/30 17:58:54.348928 [INFO] Account registered.
Requesting a certificate for sub.example.com
IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: sub.example.com
   Type:   dns
   Detail: During secondary validation: Invalid response from
   http://sub.example.com/.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI
   [107.20.106.65]: "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n
   <meta http-equiv=\"content-type\" content=\"text/html;
   charset=utf-8\">\n  <title>Page not "

----------------------------------------
/var/log/nginx/access.log
----------------------------------------
172.31.14.185 - - [30/Jan/2022:17:58:21 +0000] "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1" 404 2162 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" "18.196.102.134"
172.31.14.185 - - [30/Jan/2022:17:58:22 +0000] "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" "18.236.228.243"
172.31.14.185 - - [30/Jan/2022:17:58:22 +0000] "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" "66.133.109.36"
172.31.14.185 - - [30/Jan/2022:17:58:31 +0000] "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" "18.222.145.89"

----------------------------------------
/var/log/nginx/error.log
----------------------------------------
2022/01/30 17:58:20 [notice] 4486#4486: signal process started
2022/01/30 17:58:22 [warn] 4487#4487: *9 using uninitialized "year" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *9 using uninitialized "month" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *9 using uninitialized "day" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *9 using uninitialized "hour" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *11 using uninitialized "year" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *11 using uninitialized "month" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *11 using uninitialized "day" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:22 [warn] 4487#4487: *11 using uninitialized "hour" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:31 [warn] 4487#4487: *11 using uninitialized "year" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:31 [warn] 4487#4487: *11 using uninitialized "month" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:31 [warn] 4487#4487: *11 using uninitialized "day" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:31 [warn] 4487#4487: *11 using uninitialized "hour" variable while logging request, client: 172.31.14.185, server: sub.example.com, request: "GET /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI HTTP/1.1", host: "sub.example.com"
2022/01/30 17:58:53 [notice] 4491#4491: signal process started

----------------------------------------
/var/log/eb-engine.log
----------------------------------------
2022/01/30 17:58:17.585504 [INFO] Running command /bin/sh -c systemctl daemon-reload
2022/01/30 17:58:17.680658 [INFO] Running command /bin/sh -c systemctl reset-failed
2022/01/30 17:58:17.685474 [INFO] Register application processes...
2022/01/30 17:58:17.685486 [INFO] Registering the proc: web

2022/01/30 17:58:17.685498 [INFO] Running command /bin/sh -c systemctl show -p PartOf web.service
2022/01/30 17:58:17.691588 [INFO] Running command /bin/sh -c systemctl daemon-reload
2022/01/30 17:58:17.778134 [INFO] Running command /bin/sh -c systemctl reset-failed
2022/01/30 17:58:17.782568 [INFO] Running command /bin/sh -c systemctl is-enabled eb-app.target
2022/01/30 17:58:17.786244 [INFO] Running command /bin/sh -c systemctl enable eb-app.target
2022/01/30 17:58:17.881674 [INFO] Running command /bin/sh -c systemctl start eb-app.target
2022/01/30 17:58:17.887119 [INFO] Running command /bin/sh -c systemctl enable web.service
2022/01/30 17:58:17.984848 [INFO] Running command /bin/sh -c systemctl show -p PartOf web.service
2022/01/30 17:58:17.990266 [INFO] Running command /bin/sh -c systemctl is-active web.service
2022/01/30 17:58:17.993666 [INFO] Running command /bin/sh -c systemctl start web.service
2022/01/30 17:58:18.412552 [INFO] Executing instruction: start X-Ray
2022/01/30 17:58:18.412570 [INFO] X-Ray is not enabled.
2022/01/30 17:58:18.412576 [INFO] Executing instruction: start proxy with new configuration
2022/01/30 17:58:18.412613 [INFO] Running command /bin/sh -c /usr/sbin/nginx -t -c /var/proxy/staging/nginx/nginx.conf
2022/01/30 17:58:18.438413 [INFO] Running command /bin/sh -c cp -rp /var/proxy/staging/nginx/* /etc/nginx
2022/01/30 17:58:18.444085 [INFO] Running command /bin/sh -c systemctl show -p PartOf nginx.service
2022/01/30 17:58:18.459610 [INFO] Running command /bin/sh -c systemctl daemon-reload
2022/01/30 17:58:18.596722 [INFO] Running command /bin/sh -c systemctl reset-failed
2022/01/30 17:58:18.601333 [INFO] Running command /bin/sh -c systemctl show -p PartOf nginx.service
2022/01/30 17:58:18.612251 [INFO] Running command /bin/sh -c systemctl is-active nginx.service
2022/01/30 17:58:18.618702 [INFO] Running command /bin/sh -c systemctl start nginx.service
2022/01/30 17:58:18.696121 [INFO] Executing instruction: configureSqsd
2022/01/30 17:58:18.696138 [INFO] This is a web server environment instance, skip configure sqsd daemon ...
2022/01/30 17:58:18.696143 [INFO] Executing instruction: startSqsd
2022/01/30 17:58:18.696147 [INFO] This is a web server environment instance, skip start sqsd daemon ...
2022/01/30 17:58:18.696152 [INFO] Executing instruction: Track pids in healthd
2022/01/30 17:58:18.696157 [INFO] This is an enhanced health env...
2022/01/30 17:58:18.696171 [INFO] Running command /bin/sh -c systemctl show -p ConsistsOf aws-eb.target | cut -d= -f2
2022/01/30 17:58:18.711442 [INFO] nginx.service healthd.service cfn-hup.service

2022/01/30 17:58:18.711474 [INFO] Running command /bin/sh -c systemctl show -p ConsistsOf eb-app.target | cut -d= -f2
2022/01/30 17:58:18.723246 [INFO] web.service

2022/01/30 17:58:18.723613 [INFO] Executing instruction: RunAppDeployPostDeployHooks
2022/01/30 17:58:18.723662 [INFO] Executing platform hooks in .platform/hooks/postdeploy/
2022/01/30 17:58:18.723737 [INFO] Following platform hooks will be executed in order: [00_get_certificate.sh]
2022/01/30 17:58:18.723752 [INFO] Running platform hook: .platform/hooks/postdeploy/00_get_certificate.sh
2022/01/30 17:58:54.348954 [ERROR] An error occurred during execution of command [app-deploy] - [RunAppDeployPostDeployHooks]. Stop running the command. Error: Command .platform/hooks/postdeploy/00_get_certificate.sh failed with error exit status 1. Stderr:Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Performing the following challenges:
http-01 challenge for sub.example.com
Waiting for verification...
Challenge failed for domain sub.example.com
http-01 challenge for sub.example.com
Cleaning up challenges
Some challenges have failed.
 

2022/01/30 17:58:54.348964 [INFO] Executing cleanup logic
2022/01/30 17:58:54.349077 [INFO] CommandService Response: {"status":"FAILURE","api_version":"1.0","results":[{"status":"FAILURE","msg":"Engine execution has encountered an error.","returncode":1,"events":[{"msg":"Instance deployment successfully generated a 'Procfile'.","timestamp":1643565466,"severity":"INFO"},{"msg":"Instance deployment failed. For details, see 'eb-engine.log'.","timestamp":1643565534,"severity":"ERROR"}]}]}

2022/01/30 17:58:54.349260 [INFO] Platform Engine finished execution on command: app-deploy

2022/01/30 18:00:32.199383 [INFO] Starting...
2022/01/30 18:00:32.199429 [INFO] Starting EBPlatform-PlatformEngine
2022/01/30 18:00:32.199445 [INFO] reading event message file
2022/01/30 18:00:32.199571 [INFO] no eb envtier info file found, skip loading env tier info.
2022/01/30 18:00:32.199632 [INFO] Engine received EB command cfn-hup-exec

----------------------------------------
/var/log/web.stdout.log
----------------------------------------
Jan 30 17:55:30 ip-172-31-7-79 web: [2022-01-30 17:55:30 +0000] [3495] [INFO] Starting gunicorn 20.1.0
Jan 30 17:55:30 ip-172-31-7-79 web: [2022-01-30 17:55:30 +0000] [3495] [INFO] Listening at: http://127.0.0.1:8000 (3495)
Jan 30 17:55:30 ip-172-31-7-79 web: [2022-01-30 17:55:30 +0000] [3495] [INFO] Using worker: gthread
Jan 30 17:55:30 ip-172-31-7-79 web: [2022-01-30 17:55:30 +0000] [3551] [INFO] Booting worker with pid: 3551
Jan 30 17:56:11 ip-172-31-7-79 web: [2022-01-30 17:56:11 +0000] [3495] [INFO] Handling signal: term
Jan 30 17:56:12 ip-172-31-7-79 web: [2022-01-30 17:56:12 +0000] [3551] [INFO] Worker exiting (pid: 3551)
Jan 30 17:56:12 ip-172-31-7-79 web: [2022-01-30 17:56:12 +0000] [3495] [INFO] Shutting down: Master
Jan 30 17:56:13 ip-172-31-7-79 web: [2022-01-30 17:56:13 +0000] [3900] [INFO] Starting gunicorn 20.1.0
Jan 30 17:56:13 ip-172-31-7-79 web: [2022-01-30 17:56:13 +0000] [3900] [INFO] Listening at: http://127.0.0.1:8000 (3900)
Jan 30 17:56:13 ip-172-31-7-79 web: [2022-01-30 17:56:13 +0000] [3900] [INFO] Using worker: gthread
Jan 30 17:56:13 ip-172-31-7-79 web: [2022-01-30 17:56:13 +0000] [3958] [INFO] Booting worker with pid: 3958
Jan 30 17:56:27 ip-172-31-7-79 web: Not Found: /static/admin/css/fonts.css
Jan 30 17:56:28 ip-172-31-7-79 web: Not Found: /favicon.ico
Jan 30 17:58:17 ip-172-31-7-79 web: [2022-01-30 17:58:17 +0000] [3900] [INFO] Handling signal: term
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [3958] [INFO] Worker exiting (pid: 3958)
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [3900] [INFO] Shutting down: Master
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [4422] [INFO] Starting gunicorn 20.1.0
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [4422] [INFO] Listening at: http://127.0.0.1:8000 (4422)
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [4422] [INFO] Using worker: gthread
Jan 30 17:58:18 ip-172-31-7-79 web: [2022-01-30 17:58:18 +0000] [4479] [INFO] Booting worker with pid: 4479
Jan 30 17:58:21 ip-172-31-7-79 web: Not Found: /.well-known/acme-challenge/Gzo8gzkIEbLmtvGkSDhnNheml9XxNsctHJA3ufA0FYI
1 Answers

You might want to check the security group attached to your elastic beanstalk environment. Try adding an inbound rule which will allow all traffic for all ip ranges. (Not an ideal approach but could help)

In my case I had limited ip ranges which could connect to the website and certbot was unable to run challenges.

Related