Fix certificate request logic & S6-Overlay (#1166)

* Fix certificate request logic (#1148)

* Fix Certbot logic

* Resolved multiple directory issue

* Only scan for directories

* Typo

* Quote the path passed to realpath

* Use find and awk and sort and tail instead of ls

* Add numeric flag to sort

* Remove unnecessary if..then in awk

* Update run.sh

* Update run.sh

* Update run.sh

Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>

* S6-overlay

* Fix version

* Fix lint

* Fix check
This commit is contained in:
Pascal Vizeli
2020-03-25 23:45:46 +01:00
committed by GitHub
parent e0853ec306
commit a258fdc96d
9 changed files with 155 additions and 164 deletions

View File

@@ -14,7 +14,7 @@ variables:
jobs: jobs:
- job: "Hadolint" - job: "Hadolint"
pool: pool:
vmImage: "ubuntu-16.04" vmImage: "ubuntu-latest"
steps: steps:
- script: sudo docker pull hadolint/hadolint:$(versionHadolint) - script: sudo docker pull hadolint/hadolint:$(versionHadolint)
displayName: "Install Hadolint" displayName: "Install Hadolint"
@@ -32,20 +32,19 @@ jobs:
- job: "ShellCheck" - job: "ShellCheck"
pool: pool:
vmImage: "ubuntu-16.04" vmImage: "ubuntu-latest"
steps: steps:
- script: sudo docker pull koalaman/shellcheck:$(versionShellCheck) - script: sudo docker pull koalaman/shellcheck:$(versionShellCheck)
displayName: "Install ShellCheck" displayName: "Install ShellCheck"
- script: | - script: |
shopt -s globstar shopt -s globstar
sudo docker run --rm -i \ sudo docker run --rm -i \
-v $(pwd):/mnt:ro -e SHELLCHECK_OPTS="-e SC1008" \ -v $(pwd):/mnt:ro koalaman/shellcheck:$(versionShellCheck) -s bash **/{*.sh,run}
koalaman/shellcheck:$(versionShellCheck) **/*.sh
displayName: "Run ShellCheck" displayName: "Run ShellCheck"
- job: "JQ" - job: "JQ"
pool: pool:
vmImage: "ubuntu-16.04" vmImage: "ubuntu-latest"
steps: steps:
- script: sudo apt-get install -y jq - script: sudo apt-get install -y jq
displayName: "Install JQ" displayName: "Install JQ"

View File

@@ -1,61 +1,41 @@
# Changelog # Changelog
## 4.7 ## 4.7.0
- Fix issue with DNS challenge - Fix issue with DNS challenge
- Convert to s6-overlay
## 4.6 ## 4.6.0
- Streamline propagation seconds - Streamline propagation seconds
- Add propagation seconds to CloudFlare / option selection - Add propagation seconds to CloudFlare / option selection
## 4.5 ## 4.5.0
- Update cerbot to 1.2.0 - Update cerbot to 1.2.0
- Update image to Alpine 3.11 - Update image to Alpine 3.11
- Support CloudFlare API Token - Support CloudFlare API Token
## 4.4 ## 4.4.0
- Added support for nectup dns - Added support for nectup dns
## 4.3 ## 4.3.0
- Added support for google dns - Added support for google dns
- Fixed AWS support - Fixed AWS support
- Updated documentation - Updated documentation
- Update cerbot to 1.0.0 - Update cerbot to 1.0.0
## 4.2 ## 4.2.0
- Bugfix default empty dns setting - Bugfix default empty dns setting
## 4.1 ## 4.1.0
- Pin image to Alpine3.10 - Pin image to Alpine3.10
- Bugfix default options with empty dns - Bugfix default options with empty dns
## 4.0 ## 4.0.0
- Added support for dns challenges - Added support for dns challenges
## 3.0
- Use our Python base images with cerbot 0.32.0
## 2.3
- Update certbot to 0.30.2
## 2.2
- Bugfix not exists jq
## 2.1
- Bugfix wrong python package (py2-future)
## 2.0
- Update base image
- Remove support for TLS-SNI

View File

@@ -35,6 +35,4 @@ RUN apk add --no-cache --update \
&& apk del .build-dependencies && apk del .build-dependencies
# Copy data # Copy data
COPY data/run.sh / COPY rootfs /
CMD [ "/run.sh" ]

View File

@@ -1,6 +1,6 @@
{ {
"name": "Let's Encrypt", "name": "Let's Encrypt",
"version": "4.7", "version": "4.7.0",
"slug": "letsencrypt", "slug": "letsencrypt",
"description": "Manage certificate from Let's Encrypt", "description": "Manage certificate from Let's Encrypt",
"url": "https://github.com/home-assistant/hassio-addons/tree/master/letsencrypt", "url": "https://github.com/home-assistant/hassio-addons/tree/master/letsencrypt",

View File

@@ -1,125 +0,0 @@
#!/usr/bin/env bashio
EMAIL=$(bashio::config 'email')
DOMAINS=$(bashio::config 'domains')
KEYFILE=$(bashio::config 'keyfile')
CERTFILE=$(bashio::config 'certfile')
CHALLENGE=$(bashio::config 'challenge')
DNS_PROVIDER=$(bashio::config 'dns.provider')
if [ "${CHALLENGE}" == "dns" ]; then
bashio::log.info "Selected DNS Provider: ${DNS_PROVIDER}"
PROPAGATION_SECONDS=60
if bashio::config.exists 'dns.propagation_seconds'; then
PROPAGATION_SECONDS="$(bashio::config 'dns.propagation_seconds')"
fi
bashio::log.info "Use propagation seconds: ${PROPAGATION_SECONDS}"
else
bashio::log.info "Selected http verification"
fi
CERT_DIR=/data/letsencrypt
WORK_DIR=/data/workdir
mkdir -p "$WORK_DIR"
mkdir -p "$CERT_DIR"
mkdir -p "/ssl"
chmod +x /run.sh
touch /data/dnsapikey
PROVIDER_ARGUMENTS=()
echo -e "dns_cloudxns_api_key = $(bashio::config 'dns.cloudxns_api_key')\n" \
"dns_cloudxns_secret_key = $(bashio::config 'dns.cloudxns_secret_key')\n" \
"dns_digitalocean_token = $(bashio::config 'dns.digitalocean_token')\n" \
"dns_dnsimple_token = $(bashio::config 'dns.dnsimple_token')\n" \
"dns_dnsmadeeasy_api_key = $(bashio::config 'dns.dnsmadeeasy_api_key')\n" \
"dns_dnsmadeeasy_secret_key = $(bashio::config 'dns.dnsmadeeasy_secret_key')\n" \
"dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')\n" \
"dns_gehirn_api_secret = $(bashio::config 'dns.gehirn_api_secret')\n" \
"dns_linode_key = $(bashio::config 'dns.linode_key')\n" \
"dns_linode_version = $(bashio::config 'dns.linode_version')\n" \
"dns_luadns_email = $(bashio::config 'dns.luadns_email')\n" \
"dns_luadns_token = $(bashio::config 'dns.luadns_token')\n" \
"certbot_dns_netcup:dns_netcup_customer_id = $(bashio::config 'dns.netcup_customer_id')\n" \
"certbot_dns_netcup:dns_netcup_api_key = $(bashio::config 'dns.netcup_api_key')\n" \
"certbot_dns_netcup:dns_netcup_api_password = $(bashio::config 'dns.netcup_api_password')\n" \
"dns_nsone_api_key = $(bashio::config 'dns.nsone_api_key')\n" \
"dns_ovh_endpoint = $(bashio::config 'dns.ovh_endpoint')\n" \
"dns_ovh_application_key = $(bashio::config 'dns.ovh_application_key')\n" \
"dns_ovh_application_secret = $(bashio::config 'dns.ovh_application_secret')\n" \
"dns_ovh_consumer_key = $(bashio::config 'dns.ovh_consumer_key')\n" \
"dns_rfc2136_server = $(bashio::config 'dns.rfc2136_server')\n" \
"dns_rfc2136_port = $(bashio::config 'dns.rfc2136_port')\n" \
"dns_rfc2136_name = $(bashio::config 'dns.rfc2136_name')\n" \
"dns_rfc2136_secret = $(bashio::config 'dns.rfc2136_secret')\n" \
"dns_rfc2136_algorithm = $(bashio::config 'dns.rfc2136_algorithm')\n" \
"aws_access_key_id = $(bashio::config 'dns.aws_access_key_id')\n" \
"aws_secret_access_key = $(bashio::config 'dns.aws_secret_access_key')\n" \
"dns_sakuracloud_api_token = $(bashio::config 'dns.sakuracloud_api_token')\n" \
"dns_sakuracloud_api_secret = $(bashio::config 'dns.sakuracloud_api_secret')" > /data/dnsapikey
chmod 600 /data/dnsapikey
# AWS
if bashio::config.exists 'dns.aws_access_key_id' && bashio::config.exists 'dns.aws_secret_access_key'; then
AWS_ACCESS_KEY_ID="$(bashio::config 'dns.aws_access_key_id')"
AWS_SECRET_ACCESS_KEY="$(bashio::config 'dns.aws_secret_access_key')"
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}")
#Google
elif bashio::config.exists 'dns.google_creds'; then
GOOGLE_CREDS="$(bashio::config 'dns.google_creds')"
export GOOGLE_CREDS
if [ -f "/share/${GOOGLE_CREDS}" ]; then
cp -f "/share/${GOOGLE_CREDS}" "/data/${GOOGLE_CREDS}"
chmod 600 "/data/${GOOGLE_CREDS}"
else
bashio::log.info "Google Credentials File doesnt exists in folder share."
fi
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/${GOOGLE_CREDS}")
#Netcup
elif bashio::config.exists 'dns.netcup_customer_id' && bashio::config.exists 'dns.netcup_api_key' && bashio::config.exists 'dns.netcup_api_password'; then
PROVIDER_ARGUMENTS+=("--authenticator" "certbot-dns-netcup:dns-netcup" "--certbot-dns-netcup:dns-netcup-credentials" /data/dnsapikey "--certbot-dns-netcup:dns-netcup-propagation-seconds" "${PROPAGATION_SECONDS}")
# CloudFlare
elif [ "${DNS_PROVIDER}" == "dns-cloudflare" ]; then
if bashio::config.exists 'dns.cloudflare_api_token'; then
bashio::log.info "Use CloudFlare token"
echo "dns_cloudflare_api_token = $(bashio::config 'dns.cloudflare_api_token')" >> /data/dnsapikey
else
bashio::log.warning "Use CloudFlare global key (not recommended!)"
echo -e "dns_cloudflare_email = $(bashio::config 'dns.cloudflare_email')\n" \
"dns_cloudflare_api_key = $(bashio::config 'dns.cloudflare_api_key')\n" >> /data/dnsapikey
fi
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey "--dns-cloudflare-propagation-seconds" "${PROPAGATION_SECONDS}")
#All others
else
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey)
fi
# Generate new certs
if [ ! -d "$CERT_DIR/live" ]; then
DOMAIN_ARR=()
for line in $DOMAINS; do
DOMAIN_ARR+=(-d "$line")
done
echo "$DOMAINS" > /data/domains.gen
if [ "$CHALLENGE" == "dns" ]; then
certbot certonly --non-interactive --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" "${PROVIDER_ARGUMENTS[@]}" --email "$EMAIL" --agree-tos --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" --preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}"
else
certbot certonly --non-interactive --standalone --email "$EMAIL" --agree-tos --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" --preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}"
fi
else
certbot renew --non-interactive --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" --preferred-challenges "$CHALLENGE"
fi
# copy certs to store
cp "$CERT_DIR"/live/*/privkey.pem "/ssl/$KEYFILE"
cp "$CERT_DIR"/live/*/fullchain.pem "/ssl/$CERTFILE"

View File

@@ -0,0 +1,39 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Init folder & structures
# ==============================================================================
mkdir -p /data/workdir
mkdir -p /data/letsencrypt
# Setup Let's encrypt config
echo -e "dns_cloudxns_api_key = $(bashio::config 'dns.cloudxns_api_key')\n" \
"dns_cloudxns_secret_key = $(bashio::config 'dns.cloudxns_secret_key')\n" \
"dns_digitalocean_token = $(bashio::config 'dns.digitalocean_token')\n" \
"dns_dnsimple_token = $(bashio::config 'dns.dnsimple_token')\n" \
"dns_dnsmadeeasy_api_key = $(bashio::config 'dns.dnsmadeeasy_api_key')\n" \
"dns_dnsmadeeasy_secret_key = $(bashio::config 'dns.dnsmadeeasy_secret_key')\n" \
"dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')\n" \
"dns_gehirn_api_secret = $(bashio::config 'dns.gehirn_api_secret')\n" \
"dns_linode_key = $(bashio::config 'dns.linode_key')\n" \
"dns_linode_version = $(bashio::config 'dns.linode_version')\n" \
"dns_luadns_email = $(bashio::config 'dns.luadns_email')\n" \
"dns_luadns_token = $(bashio::config 'dns.luadns_token')\n" \
"certbot_dns_netcup:dns_netcup_customer_id = $(bashio::config 'dns.netcup_customer_id')\n" \
"certbot_dns_netcup:dns_netcup_api_key = $(bashio::config 'dns.netcup_api_key')\n" \
"certbot_dns_netcup:dns_netcup_api_password = $(bashio::config 'dns.netcup_api_password')\n" \
"dns_nsone_api_key = $(bashio::config 'dns.nsone_api_key')\n" \
"dns_ovh_endpoint = $(bashio::config 'dns.ovh_endpoint')\n" \
"dns_ovh_application_key = $(bashio::config 'dns.ovh_application_key')\n" \
"dns_ovh_application_secret = $(bashio::config 'dns.ovh_application_secret')\n" \
"dns_ovh_consumer_key = $(bashio::config 'dns.ovh_consumer_key')\n" \
"dns_rfc2136_server = $(bashio::config 'dns.rfc2136_server')\n" \
"dns_rfc2136_port = $(bashio::config 'dns.rfc2136_port')\n" \
"dns_rfc2136_name = $(bashio::config 'dns.rfc2136_name')\n" \
"dns_rfc2136_secret = $(bashio::config 'dns.rfc2136_secret')\n" \
"dns_rfc2136_algorithm = $(bashio::config 'dns.rfc2136_algorithm')\n" \
"aws_access_key_id = $(bashio::config 'dns.aws_access_key_id')\n" \
"aws_secret_access_key = $(bashio::config 'dns.aws_secret_access_key')\n" \
"dns_sakuracloud_api_token = $(bashio::config 'dns.sakuracloud_api_token')\n" \
"dns_sakuracloud_api_secret = $(bashio::config 'dns.sakuracloud_api_secret')" > /data/dnsapikey
chmod 600 /data/dnsapikey

View File

@@ -0,0 +1,5 @@
#!/usr/bin/execlineb -S0
# ==============================================================================
# Take down the S6 supervision tree
# ==============================================================================
s6-svscanctl -t /var/run/s6/services

View File

@@ -0,0 +1,95 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Start sshd service if enabled
# ==============================================================================
CERT_DIR=/data/letsencrypt
WORK_DIR=/data/workdir
PROVIDER_ARGUMENTS=()
EMAIL=$(bashio::config 'email')
DOMAINS=$(bashio::config 'domains')
KEYFILE=$(bashio::config 'keyfile')
CERTFILE=$(bashio::config 'certfile')
CHALLENGE=$(bashio::config 'challenge')
DNS_PROVIDER=$(bashio::config 'dns.provider')
if [ "${CHALLENGE}" == "dns" ]; then
bashio::log.info "Selected DNS Provider: ${DNS_PROVIDER}"
PROPAGATION_SECONDS=60
if bashio::config.exists 'dns.propagation_seconds'; then
PROPAGATION_SECONDS="$(bashio::config 'dns.propagation_seconds')"
fi
bashio::log.info "Use propagation seconds: ${PROPAGATION_SECONDS}"
else
bashio::log.info "Selected http verification"
fi
# AWS
if bashio::config.exists 'dns.aws_access_key_id' && bashio::config.exists 'dns.aws_secret_access_key'; then
AWS_ACCESS_KEY_ID="$(bashio::config 'dns.aws_access_key_id')"
AWS_SECRET_ACCESS_KEY="$(bashio::config 'dns.aws_secret_access_key')"
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}")
#Google
elif bashio::config.exists 'dns.google_creds'; then
GOOGLE_CREDS="$(bashio::config 'dns.google_creds')"
export GOOGLE_CREDS
if [ -f "/share/${GOOGLE_CREDS}" ]; then
cp -f "/share/${GOOGLE_CREDS}" "/data/${GOOGLE_CREDS}"
chmod 600 "/data/${GOOGLE_CREDS}"
else
bashio::log.info "Google Credentials File doesnt exists in folder share."
fi
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/${GOOGLE_CREDS}")
#Netcup
elif bashio::config.exists 'dns.netcup_customer_id' && bashio::config.exists 'dns.netcup_api_key' && bashio::config.exists 'dns.netcup_api_password'; then
PROVIDER_ARGUMENTS+=("--authenticator" "certbot-dns-netcup:dns-netcup" "--certbot-dns-netcup:dns-netcup-credentials" /data/dnsapikey "--certbot-dns-netcup:dns-netcup-propagation-seconds" "${PROPAGATION_SECONDS}")
# CloudFlare
elif [ "${DNS_PROVIDER}" == "dns-cloudflare" ]; then
if bashio::config.exists 'dns.cloudflare_api_token'; then
bashio::log.info "Use CloudFlare token"
echo "dns_cloudflare_api_token = $(bashio::config 'dns.cloudflare_api_token')" >> /data/dnsapikey
else
bashio::log.warning "Use CloudFlare global key (not recommended!)"
echo -e "dns_cloudflare_email = $(bashio::config 'dns.cloudflare_email')\n" \
"dns_cloudflare_api_key = $(bashio::config 'dns.cloudflare_api_key')\n" >> /data/dnsapikey
fi
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey "--dns-cloudflare-propagation-seconds" "${PROPAGATION_SECONDS}")
#All others
else
PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey)
fi
# Gather all domains into a plaintext file
DOMAIN_ARR=()
for line in $DOMAINS; do
DOMAIN_ARR+=(-d "$line")
done
echo "$DOMAINS" > /data/domains.gen
# Generate a new certificate if necessary or expand a previous certificate if domains has changed
if [ "$CHALLENGE" == "dns" ]; then
certbot certonly --non-interactive --keep-until-expiring --expand \
--email "$EMAIL" --agree-tos \
--config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \
--preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}" "${PROVIDER_ARGUMENTS[@]}"
else
certbot certonly --non-interactive --keep-until-expiring --expand \
--email "$EMAIL" --agree-tos \
--config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \
--preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}" --standalone
fi
# Get the last modified cert directory and copy the cert and private key to store
# shellcheck disable=SC2012
CERT_DIR_LATEST="$(ls -td $CERT_DIR/live/*/ | head -1)"
cp "${CERT_DIR_LATEST}privkey.pem" "/ssl/$KEYFILE"
cp "${CERT_DIR_LATEST}fullchain.pem" "/ssl/$CERTFILE"

View File

@@ -3,6 +3,6 @@
# Start ttyd service for ingress # Start ttyd service for ingress
# ============================================================================== # ==============================================================================
bashio::log.info "Starting Web Terminal..." bashio::log.info "Starting Web Terminal..."
cd /root cd /root || bashio::exit.nok "Can't find root folder!"
exec ttyd -p 8099 tmux -u new -A -s homeassistant bash -l exec ttyd -p 8099 tmux -u new -A -s homeassistant bash -l