From 32b00d6f9187d0fc6abfde83825a6d3ead821539 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 09:58:10 -0800 Subject: [PATCH 1/9] Attempt (yet again) to get the script to run consistently - Switched to a forever-running script in `run` - bump the build base image - bump cryptography to 41.0.5 - bump certbot to 2.7.4 --- iot-certbot/CHANGELOG.md | 7 +++ iot-certbot/build.yaml | 19 +++--- .../rootfs/etc/services.d/lets-encrypt/finish | 1 + .../rootfs/etc/services.d/lets-encrypt/run | 60 ++----------------- iot-certbot/rootfs/opt/letsencrypt/bin/renew | 59 ++++++++++++++++++ iot-certbot/test/.gitignore | 4 ++ iot-certbot/test/README.md | 16 +++++ .../cache/addons.self.options.config.cache | 5 ++ iot-certbot/test/config/.gitignore | 0 iot-certbot/test/data/.gitignore | 0 iot-certbot/test/ssl/.gitignore | 0 11 files changed, 110 insertions(+), 61 deletions(-) create mode 100755 iot-certbot/rootfs/opt/letsencrypt/bin/renew create mode 100644 iot-certbot/test/.gitignore create mode 100644 iot-certbot/test/README.md create mode 100644 iot-certbot/test/cache/addons.self.options.config.cache create mode 100644 iot-certbot/test/config/.gitignore create mode 100644 iot-certbot/test/data/.gitignore create mode 100644 iot-certbot/test/ssl/.gitignore diff --git a/iot-certbot/CHANGELOG.md b/iot-certbot/CHANGELOG.md index 3b46a43..cb75d2a 100644 --- a/iot-certbot/CHANGELOG.md +++ b/iot-certbot/CHANGELOG.md @@ -1,5 +1,12 @@ +## 1.1.1 + +- Switched to a forever-running script in `run` +- bump the build base image +- bump cryptography to 41.0.5 +- bump certbot to 2.7.4 + ## 1.1.0 Stop trying to run periodically, depend on automations diff --git a/iot-certbot/build.yaml b/iot-certbot/build.yaml index 1803512..b9b0447 100644 --- a/iot-certbot/build.yaml +++ b/iot-certbot/build.yaml @@ -1,10 +1,15 @@ --- build_from: - aarch64: ghcr.io/home-assistant/aarch64-base-python:3.9-alpine3.14 - amd64: ghcr.io/home-assistant/amd64-base-python:3.9-alpine3.14 - armhf: ghcr.io/home-assistant/armhf-base-python:3.9-alpine3.14 - armv7: ghcr.io/home-assistant/armv7-base-python:3.9-alpine3.14 - i386: ghcr.io/home-assistant/i386-base-python:3.9-alpine3.14 + aarch64: "ghcr.io/home-assistant/aarch64-base:3.15" + amd64: "ghcr.io/home-assistant/amd64-base:3.15" + armhf: "ghcr.io/home-assistant/armhf-base:3.15" + armv7: "ghcr.io/home-assistant/armv7-base:3.15" + i386: "ghcr.io/home-assistant/i386-base:3.15" +labels: + org.opencontainers.image.title: "Home Assistant Add-on: AWS IOT Certbot" + org.opencontainers.image.description: "Use AWS IOT and LetsEncrpyt for DNS challenge certs" + org.opencontainers.image.source: "https://github.com/offbyone/homeassistant-addons" + org.opencontainers.image.licenses: "BSD" args: - CRYPTOGRAPHY_VERSION: 39.0.0 - CERTBOT_VERSION: 2.1.0 + CRYPTOGRAPHY_VERSION: 41.0.5 + CERTBOT_VERSION: 2.7.4 diff --git a/iot-certbot/rootfs/etc/services.d/lets-encrypt/finish b/iot-certbot/rootfs/etc/services.d/lets-encrypt/finish index 0e3cee2..bfd45b2 100755 --- a/iot-certbot/rootfs/etc/services.d/lets-encrypt/finish +++ b/iot-certbot/rootfs/etc/services.d/lets-encrypt/finish @@ -1,4 +1,5 @@ #!/usr/bin/env bashio +# -*- shell-script -*- # ============================================================================== # Take down the S6 supervision tree when letsencrypt fails # s6-overlay docs: https://github.com/just-containers/s6-overlay diff --git a/iot-certbot/rootfs/etc/services.d/lets-encrypt/run b/iot-certbot/rootfs/etc/services.d/lets-encrypt/run index c77ba8b..f38fe41 100755 --- a/iot-certbot/rootfs/etc/services.d/lets-encrypt/run +++ b/iot-certbot/rootfs/etc/services.d/lets-encrypt/run @@ -1,58 +1,10 @@ #!/usr/bin/with-contenv bashio +# -*- shell-script -*- # ============================================================================== -# Start sshd service if enabled +# Re-run the renew script forever, until the addon is stopped. Hourly ought to +# be good enough. # ============================================================================== -CERT_DIR=/data/letsencrypt -WORK_DIR=/data/workdir -PROVIDER_ARGUMENTS=() -ACME_CUSTOM_SERVER_ARGUMENTS=() - -EMAIL=$(bashio::config 'email') -DOMAINS=$(bashio::config 'domains') -KEYFILE=$(bashio::config 'keyfile') -CERTFILE=$(bashio::config 'certfile') -ACME_SERVER=$(bashio::config 'acme_server') -ACME_ROOT_CA=$(bashio::config 'acme_root_ca_cert') - -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}" - -# ensure our current credentials are up to date -/opt/iot/bin/update-credentials.sh - -# Source our current credentials -AWS_CONFIG_FILE=/opt/iot/credentials/default -export AWS_CONFIG_FILE -PROVIDER_ARGUMENTS+=("--dns-route53") - -if bashio::config.has_value 'acme_server' ; then - ACME_CUSTOM_SERVER_ARGUMENTS+=("--server" "${ACME_SERVER}") - - if bashio::config.has_value 'acme_root_ca_cert'; then - echo "${ACME_ROOT_CA}" > /tmp/root-ca-cert.crt - # Certbot will automatically open the filepath contained in REQUESTS_CA_BUNDLE for extra CA cert - export REQUESTS_CA_BUNDLE=/tmp/root-ca-cert.crt - fi -fi - -# Gather all domains into a plaintext file -DOMAIN_ARR=() -for line in $DOMAINS; do - DOMAIN_ARR+=(-d "$line") +while true; do + /opt/letsencrypt/bin/renew || bashio::log.error "Most recent letsencrypt run failed; check your logs" + sleep 3600 done -echo "$DOMAINS" > /data/domains.gen - -certbot certonly --non-interactive --keep-until-expiring --expand \ - --email "$EMAIL" --agree-tos \ - --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \ - --preferred-challenges "dns" "${DOMAIN_ARR[@]}" "${PROVIDER_ARGUMENTS[@]}" \ - --preferred-chain "ISRG Root X1" - -# 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" diff --git a/iot-certbot/rootfs/opt/letsencrypt/bin/renew b/iot-certbot/rootfs/opt/letsencrypt/bin/renew new file mode 100755 index 0000000..cd54b04 --- /dev/null +++ b/iot-certbot/rootfs/opt/letsencrypt/bin/renew @@ -0,0 +1,59 @@ +#!/usr/bin/with-contenv bashio +# -*- shell-script -*- +# ============================================================================== +# Start sshd service if enabled +# ============================================================================== +CERT_DIR=/data/letsencrypt +WORK_DIR=/data/workdir +PROVIDER_ARGUMENTS=() +ACME_CUSTOM_SERVER_ARGUMENTS=() + +EMAIL=$(bashio::config 'email') +DOMAINS=$(bashio::config 'domains') +KEYFILE=$(bashio::config 'keyfile') +CERTFILE=$(bashio::config 'certfile') +ACME_SERVER=$(bashio::config 'acme_server') +ACME_ROOT_CA=$(bashio::config 'acme_root_ca_cert') + +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}" + +# ensure our current credentials are up to date +/opt/iot/bin/update-credentials.sh + +# Source our current credentials +AWS_CONFIG_FILE=/opt/iot/credentials/default +export AWS_CONFIG_FILE +PROVIDER_ARGUMENTS+=("--dns-route53") + +if bashio::config.has_value 'acme_server' ; then + ACME_CUSTOM_SERVER_ARGUMENTS+=("--server" "${ACME_SERVER}") + + if bashio::config.has_value 'acme_root_ca_cert'; then + echo "${ACME_ROOT_CA}" > /tmp/root-ca-cert.crt + # Certbot will automatically open the filepath contained in REQUESTS_CA_BUNDLE for extra CA cert + export REQUESTS_CA_BUNDLE=/tmp/root-ca-cert.crt + fi +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 + +certbot certonly --non-interactive --keep-until-expiring --expand \ + --email "$EMAIL" --agree-tos \ + --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \ + --preferred-challenges "dns" "${DOMAIN_ARR[@]}" "${PROVIDER_ARGUMENTS[@]}" \ + --preferred-chain "ISRG Root X1" + +# 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" diff --git a/iot-certbot/test/.gitignore b/iot-certbot/test/.gitignore new file mode 100644 index 0000000..5a54e9e --- /dev/null +++ b/iot-certbot/test/.gitignore @@ -0,0 +1,4 @@ +config/* +data/* +ssl/* +!.gitignore diff --git a/iot-certbot/test/README.md b/iot-certbot/test/README.md new file mode 100644 index 0000000..1b229ff --- /dev/null +++ b/iot-certbot/test/README.md @@ -0,0 +1,16 @@ +# Test data for the container. + +This directory can be used to provide the necessary set of mounts for the container to act "home-assistant-ish". + +Here's a shell invocation that runs this container: + +``` shellsession +docker run --rm -it \ + -v (pwd)/test/ssl:/ssl \ + -v (pwd)/test/data:/data \ + -v (pwd)/test/cache:/tmp/.bashio/ \ + -v (pwd)/test/config:/config \ + --name iot-certbot local/iot_certbot +``` + +You should set up the necessary addon config in `test/cache` (there's an example in there that I have _not_ done the necessary work to correct, sorry :( ) diff --git a/iot-certbot/test/cache/addons.self.options.config.cache b/iot-certbot/test/cache/addons.self.options.config.cache new file mode 100644 index 0000000..97297c2 --- /dev/null +++ b/iot-certbot/test/cache/addons.self.options.config.cache @@ -0,0 +1,5 @@ +{ + "email": "le-iot-ha-addon-dev@example.com", + "domains": ["a.b.c"], + "acme_server": "https://acme-staging-v02.api.letsencrypt.org/directory" +} diff --git a/iot-certbot/test/config/.gitignore b/iot-certbot/test/config/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/iot-certbot/test/data/.gitignore b/iot-certbot/test/data/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/iot-certbot/test/ssl/.gitignore b/iot-certbot/test/ssl/.gitignore new file mode 100644 index 0000000..e69de29 From e039c4469aff66c4871c761f2e1f437299181e61 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:05:31 -0800 Subject: [PATCH 2/9] Bump a whole bunch of action versions --- .github/workflows/builder.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index b1b1878..d1a5078 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -21,12 +21,13 @@ jobs: changed: ${{ steps.changed_addons.outputs.changed }} steps: - name: Check out the repository - uses: actions/checkout@v3.0.2 + uses: actions/checkout@v4 - name: Get changed files id: changed_files # pinning out of paranoia, this is the modern-node fork of jitterbit/get-changed-files - uses: masesgroup/retrieve-changed-files@076a92699259d81d1c607bd91f0e1e9d45fd3151 + # at v3.0.0 + uses: masesgroup/retrieve-changed-files@491e80760c0e28d36ca6240a27b1ccb8e1402c13 - name: Find add-on directories id: addons @@ -71,7 +72,7 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get information id: info @@ -98,7 +99,7 @@ jobs: - name: Login to GitHub Container Registry if: env.BUILD_ARGS != '--test' - uses: docker/login-action@v2.0.0 + uses: docker/login-action@v3.0.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -106,7 +107,7 @@ jobs: - name: Build ${{ matrix.addon }} add-on if: steps.check.outputs.build_arch == 'true' - uses: home-assistant/builder@2022.11.0 + uses: home-assistant/builder@2023.09.0 with: args: | ${{ env.BUILD_ARGS }} \ From 8501fb335d42403f9b57b7248012e5449986288c Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:14:49 -0800 Subject: [PATCH 3/9] Test the addon --- .github/workflows/builder.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index d1a5078..2fc160f 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -105,8 +105,18 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Test ${{ matrix.addon }} add-on + if: steps.check.outputs.build_arch == 'true' && github.event_name == 'pull_request' + uses: home-assistant/builder@master + with: + args: | + --test \ + --all \ + --target /data/${{ matrix.addon }} \ + --docker-hub "ghcr.io/${{ github.repository_owner }}" + - name: Build ${{ matrix.addon }} add-on - if: steps.check.outputs.build_arch == 'true' + if: steps.check.outputs.build_arch == 'true' && github.event_name != 'pull_request' uses: home-assistant/builder@2023.09.0 with: args: | From e7342071e68445cea8c556682556a7981638c4a7 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:18:13 -0800 Subject: [PATCH 4/9] Always build addons when the builder changes --- .github/workflows/builder.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 2fc160f..cfd2cf3 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -38,7 +38,11 @@ jobs: run: | declare -a changed_addons for addon in ${{ steps.addons.outputs.addons }}; do - if [[ "${{ steps.changed_files.outputs.all }}" =~ $addon ]]; then + # if one of the changed files was this action, we retry all the builds + if [[ "${{ steps.changed_files.outputs.all }}" =~ .github/workflows/builder.yml ]]; then + changed_addons+=("\"${addon}\","); + echo "Including ${addon} because the build action changed" + elif [[ "${{ steps.changed_files.outputs.all }}" =~ $addon ]]; then for file in ${{ env.MONITORED_FILES }}; do if [[ "${{ steps.changed_files.outputs.all }}" =~ $addon/$file ]]; then if [[ ! "${changed_addons[@]}" =~ $addon ]]; then From eb70adbcf7192595c2372a5cff60f5075970616a Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:20:23 -0800 Subject: [PATCH 5/9] Include the image name --- .github/workflows/builder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index cfd2cf3..72901be 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -117,6 +117,7 @@ jobs: --test \ --all \ --target /data/${{ matrix.addon }} \ + --image "${{ matrix.addon }}" \ --docker-hub "ghcr.io/${{ github.repository_owner }}" - name: Build ${{ matrix.addon }} add-on From af6807ee014d545d431ccce983b74f7783c049e1 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:31:05 -0800 Subject: [PATCH 6/9] Attempt to get the lint workflow running --- .github/workflows/builder.yml | 2 +- .github/workflows/lint.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 72901be..be4d864 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -39,7 +39,7 @@ jobs: declare -a changed_addons for addon in ${{ steps.addons.outputs.addons }}; do # if one of the changed files was this action, we retry all the builds - if [[ "${{ steps.changed_files.outputs.all }}" =~ .github/workflows/builder.yml ]]; then + if [[ "${{ steps.changed_files.outputs.all }}" =~ '.github/workflows/.*\.yml' ]]; then changed_addons+=("\"${addon}\","); echo "Including ${addon} because the build action changed" elif [[ "${{ steps.changed_files.outputs.all }}" =~ $addon ]]; then diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 81b722c..c098d71 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,10 +15,10 @@ jobs: name: Find add-ons runs-on: ubuntu-latest outputs: - addons: ${{ steps.addons.outputs.addons_list }} + addons: ${{ steps.addons.outputs.addons }} steps: - name: ⤵️ Check out code from GitHub - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: 🔍 Find add-on directories id: addons @@ -33,7 +33,7 @@ jobs: path: ${{ fromJson(needs.find.outputs.addons) }} steps: - name: ⤵️ Check out code from GitHub - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: 🚀 Run Home Assistant Add-on Lint uses: frenck/action-addon-linter@v2 From 1a71b46ffc98d2e63d19cc86bc938bc6c09b303f Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:47:14 -0800 Subject: [PATCH 7/9] Either test or build, don't do both --- .github/workflows/builder.yml | 44 ++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index be4d864..ea0a726 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -64,10 +64,39 @@ jobs: else echo "No add-on had any monitored files changed (${{ env.MONITORED_FILES }})"; fi + test: + needs: init + runs-on: ubuntu-latest + if: needs.init.outputs.changed == 'true' && github.event_name == 'pull_request' + name: Verify ${{ matrix.addon }} add-on before build/publish + strategy: + matrix: + addon: ${{ fromJson(needs.init.outputs.changed_addons) }} + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Get information + id: info + uses: home-assistant/actions/helpers/info@master + with: + path: "./${{ matrix.addon }}" + + - name: Test ${{ matrix.addon }} add-on + uses: home-assistant/builder@master + with: + args: | + --test \ + --all \ + --target /data/${{ matrix.addon }} \ + --image "${{ matrix.addon }}" \ + --docker-hub "ghcr.io/${{ github.repository_owner }}" + build: needs: init runs-on: ubuntu-latest - if: needs.init.outputs.changed == 'true' + if: needs.init.outputs.changed == 'true' && github.event_name != 'pull_request' name: Build ${{ matrix.arch }} ${{ matrix.addon }} add-on strategy: matrix: @@ -109,19 +138,8 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Test ${{ matrix.addon }} add-on - if: steps.check.outputs.build_arch == 'true' && github.event_name == 'pull_request' - uses: home-assistant/builder@master - with: - args: | - --test \ - --all \ - --target /data/${{ matrix.addon }} \ - --image "${{ matrix.addon }}" \ - --docker-hub "ghcr.io/${{ github.repository_owner }}" - - name: Build ${{ matrix.addon }} add-on - if: steps.check.outputs.build_arch == 'true' && github.event_name != 'pull_request' + if: steps.check.outputs.build_arch == 'true' uses: home-assistant/builder@2023.09.0 with: args: | From 5cbcd4f7d32c5b1b35146dd4693e29bb380c36b9 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:50:15 -0800 Subject: [PATCH 8/9] Literally poking a punctuation to force a run --- .github/workflows/builder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index ea0a726..16c8799 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -25,7 +25,7 @@ jobs: - name: Get changed files id: changed_files - # pinning out of paranoia, this is the modern-node fork of jitterbit/get-changed-files + # pinning out of paranoia; this is the modern-node fork of jitterbit/get-changed-files # at v3.0.0 uses: masesgroup/retrieve-changed-files@491e80760c0e28d36ca6240a27b1ccb8e1402c13 From f20c42969c562592e0151c48b49b005f82bf36cf Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Sat, 11 Nov 2023 10:51:40 -0800 Subject: [PATCH 9/9] Use addons_list --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c098d71..9149f4b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: name: Find add-ons runs-on: ubuntu-latest outputs: - addons: ${{ steps.addons.outputs.addons }} + addons: ${{ steps.addons.outputs.addons_list }} steps: - name: ⤵️ Check out code from GitHub uses: actions/checkout@v4