Skip to content

[change] Avoid unnecessary CRL restarts when revokelist content is unchanged #589#610

Open
4f4d wants to merge 5 commits into
openwisp:masterfrom
4f4d:issues/589-openvpn-crl-cron
Open

[change] Avoid unnecessary CRL restarts when revokelist content is unchanged #589#610
4f4d wants to merge 5 commits into
openwisp:masterfrom
4f4d:issues/589-openvpn-crl-cron

Conversation

@4f4d
Copy link
Copy Markdown

@4f4d 4f4d commented May 20, 2026

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • N/A I have updated the documentation.

Reference to Existing Issue

Closes #589

Description of Changes

  • moved the OpenVPN-specific helper functions from images/common/utils.sh to images/openwisp_openvpn/openvpn_utils.sh
  • moved the base OpenVPN cron entries into images/openwisp_openvpn/openvpn.crontab and load them from init_command.sh
  • updated revokelist.sh to download the CRL into a temporary file and restart OpenVPN only when the CRL actually changes
  • changed the CRL refresh frequency from once per day to every 5 minutes now that unchanged CRLs no longer trigger restarts
  • validated TOPOLOGY_UPDATE_INTERVAL before appending the optional topology cron entry
  • hardened Redis reads and OpenVPN checksum/config downloads to fail fast on invalid or incomplete data
  • added regression coverage for the CRL restart behavior and made the affected test paths retry-safe in CI

Local Validation

  • ./run-qa-checks completed successfully
  • make compose-build completed successfully, including the patched OpenVPN image
  • validated the OpenVPN-specific runtime behavior in a container:
    • the image-local openvpn.crontab is loaded correctly
    • the first CRL download creates revoked.crl and triggers the restart path
    • an unchanged CRL does not trigger a restart
    • a changed CRL replaces revoked.crl and triggers the restart path
    • a failed CRL download preserves the existing revoked.crl and does not trigger a restart

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Extracts OpenVPN helpers into images/openwisp_openvpn/openvpn_utils.sh, moves cron entries into images/openwisp_openvpn/openvpn.crontab (installed at startup), updates init_command.sh, openvpn.sh, and revokelist.sh to source the new utilities, implements crl_download_if_changed to replace revoked.crl only on content changes and restart OpenVPN conditionally, renames a Dockerfile env var, and adds integration tests for revokelist and config-update behavior.

Sequence Diagram(s)

sequenceDiagram
  participant ComponentA
  participant ComponentB
  ComponentA->>ComponentB: observable interaction
Loading

## Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

## Suggested reviewers

- nemesifier

</details>

<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->

---

<!-- pre_merge_checks_override_start -->
> [!IMPORTANT]
> ## Pre-merge checks failed
> 
> Please resolve all errors before merging. Addressing warnings is optional.
<!-- pre_merge_checks_override_end -->

### ❌ Failed checks (1 inconclusive)

|         Check name         | Status         | Explanation                                                                                                                                                                                                                                | Resolution                                                                                                                                                                         |
| :------------------------: | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Out of Scope Changes check | ❓ Inconclusive | The changes to images/common/utils.sh include removal of 7 functions and mysterious numeric literals (197, 198, 199) in postfix_config, with file truncation that appears unintentional and disconnected from the linked issue objectives. | Clarify whether the utils.sh truncation and numeric literals are intentional; they appear unrelated to issue `#589` objectives and may indicate incomplete edits or merge conflicts. |

<details>
<summary>✅ Passed checks (4 passed)</summary>

|      Check name     | Status   | Explanation                                                                                                                                                                                                              |
| :-----------------: | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|     Title check     | ✅ Passed | The title correctly uses the [change] prefix, references issue `#589`, and clearly describes the main change about avoiding unnecessary CRL restarts when revokelist content is unchanged.                                 |
|  Description check  | ✅ Passed | The PR description is comprehensive and follows the template with all required sections: checklist items checked, issue reference (Closes `#589`), detailed description of changes, and local validation details provided. |
| Linked Issues check | ✅ Passed | All coding objectives from issue `#589` are addressed: CRL restart logic only triggers on actual changes, crontab is now visible in openvpn image directory, and OpenVPN-specific functions are moved to openvpn_utils.sh. |
|      Bug Fixes      | ✅ Passed | Fixes root cause via cmp-based change detection. Two regression tests cover all scenarios with deterministic mocks and would fail without patch.                                                                         |

</details>

<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

<details>
<summary>🧪 Generate unit tests (beta)</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-4502698471"} -->   Create PR with unit tests

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=openwisp/docker-openwisp&utm_content=610)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>


<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>

<!-- tips_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 63-71: Replace the fixed temporary filename used for CRL updates
to avoid races: in the code around local tmp_crl and calls to crl_download_to,
create a unique temp file (e.g., via mktemp or appending $$/timestamp) and
assign it to tmp_crl, use that variable for the download, comparison (cmp -s
"$tmp_crl" revoked.crl) and mv, and register a trap/cleanup to unlink tmp_crl on
failure/exit; update references to tmp_crl (the local variable and the
crl_download_to call) so all cleanup and the final move operate on the unique
temp file.
- Line 86: The cron line in openvpn_utils.sh uses a misspelled environment
variable (TOPLOGY_UPDATE_INTERVAL) causing an empty/invalid cron entry; update
the variable name to TOPLOGY_UPDATE_INTERVAL (matching the docs) in the echo
that writes the cron job and also fix the matching typo in the Dockerfile where
the variable is set so both use TOPLOGY_UPDATE_INTERVAL; ensure the cron string
still exports TOPOLOGY_UUID and TOPOLOGY_KEY as before and validate the
resulting cron syntax after the change.
- Around line 3-6: In get_redis_value(), replace the POSIX-incompatible echo -en
framing with a printf-based framing so the Redis GET request correctly includes
CRLF on ash/Alpine; use printf with a format string that inserts the key and
emits "\r\n" (e.g., printf 'GET %s\r\n' "$key") piped to nc redis 6379, keeping
the existing awk extraction unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9bc3b838-a66f-49ed-9fab-270ec767ba56

📥 Commits

Reviewing files that changed from the base of the PR and between ce822f6 and 4944e57.

📒 Files selected for processing (6)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/openwisp_openvpn/openvpn.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/revokelist.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 5-5: In POSIX sh, echo flags are undefined.

(SC3037)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-38: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 35-36: Quote this to prevent word splitting.

(SC2046)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 37-37: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 37-37: Quote this to prevent word splitting.

(SC2046)


[warning] 40-48: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 47-47: Use ./glob or -- glob so names with dashes won't become options.

(SC2035)


[warning] 50-54: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 51-51: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 56-60: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 62-77: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 63-63: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 79-88: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 81-81: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 81-81: Quote this to prevent word splitting.

(SC2046)


[warning] 82-82: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 82-82: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (4)
images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/common/init_command.sh (1)

33-39: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

7-7: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

7-17: LGTM!

Comment thread images/openwisp_openvpn/openvpn_utils.sh Outdated
Comment thread images/openwisp_openvpn/openvpn_utils.sh Outdated
@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from 4944e57 to 4d2edf4 Compare May 20, 2026 04:55
@coderabbitai coderabbitai Bot added the bug Something isn't working label May 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 3-6: The get_redis_value function currently calls `nc redis 6379`
with no timeout; modify get_redis_value to run the netcat call with a bounded
timeout (e.g. using `timeout 5 nc redis 6379` or `nc -w 5 redis 6379`) and
detect a failure so the function returns an empty string (or non-zero) instead
of blocking; ensure you still pipe the successful response into `awk 'NR==2
{gsub(/\r/, ""); print}'` and handle the case where `timeout`/`nc` exits
non-zero by not printing garbage or hanging.
- Around line 34-48: The download/checksum functions openvpn_config_checksum and
openvpn_config_download don't fail fast or validate outputs; update them to
check curl exit statuses and non-empty outputs, aborting on failure: for
openvpn_config_checksum ensure the curl call succeeds and OFILE is non-empty
(exit or retry if not), and for openvpn_config_download verify each curl exit
code and that vpn.tar.gz and checksum files have expected size/content before
extracting; after tar xzf, verify the extraction succeeded and produced the
required .pem files and set strict permissions, failing (exit non-zero)
immediately on any validation error.

In `@tests/runtests.py`:
- Around line 465-469: After generating {test_dir}/revokelist.sh with the sed
substitutions in tests/runtests.py, add a quick post-transform assertion that
the output contains the expected stubbed lines (e.g. "cd {test_dir}/work" and
"source {test_dir}/openvpn_utils.sh" or the ":" replacement for "source
/utils.sh") and does not still contain the original patterns ("cd /" or "source
/utils.sh"). Locate the sed block that writes /revokelist.sh and, immediately
after writing the file, read {test_dir}/revokelist.sh and fail fast
(raise/assert with a clear message) if those expected replacements are not
present so the test deterministically fails when the sed patch stops matching.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3122d9f-e85e-40f3-b293-e662291362fa

📥 Commits

Reviewing files that changed from the base of the PR and between 4944e57 and 4d2edf4.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/openwisp_openvpn/openvpn.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/revokelist.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-38: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 35-36: Quote this to prevent word splitting.

(SC2046)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 37-37: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 37-37: Quote this to prevent word splitting.

(SC2046)


[warning] 40-48: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 47-47: Use ./glob or -- glob so names with dashes won't become options.

(SC2035)


[warning] 50-54: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 51-51: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 56-60: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 62-82: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 63-63: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 84-93: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 86-86: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 86-86: Quote this to prevent word splitting.

(SC2046)


[warning] 87-87: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 87-87: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (5)
images/openwisp_openvpn/Dockerfile (1)

28-28: ⚡ Quick win

The typo fix is correct and consistently applied throughout the codebase.

The change from TOPLOGY_UPDATE_INTERVAL to TOPOLOGY_UPDATE_INTERVAL has been properly integrated. No references to the old misspelling remain in the codebase, and the corrected variable name is consistently used in both the environment definition (Dockerfile), the consuming script (openvpn_utils.sh), and documentation (settings.rst).

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/common/init_command.sh (1)

33-39: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

7-7: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

7-17: LGTM!

Comment thread images/openwisp_openvpn/openvpn_utils.sh
Comment thread images/openwisp_openvpn/openvpn_utils.sh
Comment thread tests/runtests.py
@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch 2 times, most recently from 86f364c to f715d95 Compare May 20, 2026 05:10
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
images/openwisp_openvpn/openvpn_utils.sh (2)

34-47: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on checksum/config download errors before applying artifacts.

These curl/tar/chmod steps currently continue on transient or malformed responses, which can trigger incorrect restart behavior.

Suggested fix
 function openvpn_config_checksum {
-	export OFILE=$(curl --silent --insecure \
-		${API_INTERNAL}/controller/vpn/checksum/$UUID/?key=$KEY)
-	export NFILE=$(cat checksum)
+	OFILE="$(curl --silent --show-error --fail --insecure \
+		"${API_INTERNAL}/controller/vpn/checksum/${UUID}/?key=${KEY}")" || return 1
+	[ -n "$OFILE" ] || return 1
+	NFILE="$(cat checksum 2>/dev/null)" || return 1
 }
 
 function openvpn_config_download {
-	curl --silent --retry 10 --retry-delay 5 --retry-max-time 300\
-		--insecure --output vpn.tar.gz \
-		${API_INTERNAL}/controller/vpn/download-config/$UUID/?key=$KEY
-	curl --silent --insecure --output checksum \
-		${API_INTERNAL}/controller/vpn/checksum/$UUID/?key=$KEY
-	tar xzf vpn.tar.gz
-	chmod 600 *.pem
+	curl --silent --show-error --fail --retry 10 --retry-delay 5 --retry-max-time 300 \
+		--insecure --output vpn.tar.gz \
+		"${API_INTERNAL}/controller/vpn/download-config/${UUID}/?key=${KEY}" || return 1
+	curl --silent --show-error --fail --insecure --output checksum \
+		"${API_INTERNAL}/controller/vpn/checksum/${UUID}/?key=${KEY}" || return 1
+	tar xzf vpn.tar.gz || return 1
+	chmod 600 -- ./*.pem || return 1
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@images/openwisp_openvpn/openvpn_utils.sh` around lines 34 - 47, The
openvpn_config_checksum and openvpn_config_download functions do not fail fast
on curl/tar/chmod failures or on empty/malformed responses; update them so each
external command is checked and the function exits non‑zero immediately on
error: in openvpn_config_checksum verify the curl exit code and that OFILE is
non-empty and well-formed before exporting, and in openvpn_config_download check
the exit codes of both curl calls, validate the downloaded checksum file (NFILE)
and compare it to OFILE (or compute a local checksum) before running tar xzf and
chmod, and ensure tar and chmod errors are caught and cause an immediate exit;
reference these functions (openvpn_config_checksum, openvpn_config_download)
when adding these validations and early returns.

5-5: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a timeout to Redis reads to avoid hanging jobs.

nc redis 6379 can block indefinitely and stall init/cron flows; use a bounded timeout and fail cleanly.

Suggested fix
-	printf 'GET %s\r\n' "$key" | nc redis 6379 | awk 'NR==2 {gsub(/\r/, ""); print}'
+	printf 'GET %s\r\n' "$key" | nc -w 5 redis 6379 | awk 'NR==2 {gsub(/\r/, ""); print}'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@images/openwisp_openvpn/openvpn_utils.sh` at line 5, The Redis read currently
uses an unbounded netcat call ("printf ... | nc redis 6379 | awk ...") which can
hang; wrap the nc call with a bounded timeout (e.g. use the timeout utility:
"timeout 5s nc redis 6379" or netcat options like "nc -w 5 -q 1") and ensure the
pipeline handles non-zero exit (treat timeout as a failure) so the script fails
cleanly instead of hanging; update the line containing printf ... | nc redis
6379 | awk 'NR==2 {gsub(/\r/, ""); print}' to use the timeout-wrapped nc and
propagate or handle its non-zero exit accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Line 91: The cron line writer currently echoes a crontab entry using
TOPOLOGY_UPDATE_INTERVAL without validation; add a guard before writing that
ensures TOPOLOGY_UPDATE_INTERVAL is non-empty and a positive integer (e.g.,
regex check like '^[0-9]+$'), and if invalid either skip creating the cron entry
and log a clear error/warning or fall back to a safe default interval; apply
this validation in the same scope that references TOPOLOGY_UPDATE_INTERVAL,
TOPOLOGY_UUID, TOPOLOGY_KEY and the /send-topology.sh cron line so the script
never writes an invalid cron entry.

In `@tests/runtests.py`:
- Around line 479-480: The test currently executes revokelist.sh with sh which
can break because the rewritten script uses the Bash-only builtin source; update
the invocation in tests/runtests.py so the command runs under bash (i.e.,
replace the use of "sh {test_dir}/revokelist.sh" with "bash
{test_dir}/revokelist.sh") so that the sourced openvpn_utils.sh and other Bash
semantics used by revokelist.sh execute correctly; ensure the environment prefix
(CRL_TEST_MODE and PATH adjustments) remains unchanged and still applies to the
bash invocation.

---

Duplicate comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 34-47: The openvpn_config_checksum and openvpn_config_download
functions do not fail fast on curl/tar/chmod failures or on empty/malformed
responses; update them so each external command is checked and the function
exits non‑zero immediately on error: in openvpn_config_checksum verify the curl
exit code and that OFILE is non-empty and well-formed before exporting, and in
openvpn_config_download check the exit codes of both curl calls, validate the
downloaded checksum file (NFILE) and compare it to OFILE (or compute a local
checksum) before running tar xzf and chmod, and ensure tar and chmod errors are
caught and cause an immediate exit; reference these functions
(openvpn_config_checksum, openvpn_config_download) when adding these validations
and early returns.
- Line 5: The Redis read currently uses an unbounded netcat call ("printf ... |
nc redis 6379 | awk ...") which can hang; wrap the nc call with a bounded
timeout (e.g. use the timeout utility: "timeout 5s nc redis 6379" or netcat
options like "nc -w 5 -q 1") and ensure the pipeline handles non-zero exit
(treat timeout as a failure) so the script fails cleanly instead of hanging;
update the line containing printf ... | nc redis 6379 | awk 'NR==2 {gsub(/\r/,
""); print}' to use the timeout-wrapped nc and propagate or handle its non-zero
exit accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a6812144-d1fb-49ab-a7e1-3540b519df2e

📥 Commits

Reviewing files that changed from the base of the PR and between 4d2edf4 and 86f364c.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/openwisp_openvpn/openvpn.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/revokelist.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-38: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 35-36: Quote this to prevent word splitting.

(SC2046)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 36-36: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 37-37: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 37-37: Quote this to prevent word splitting.

(SC2046)


[warning] 40-48: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 43-43: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 45-45: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 47-47: Use ./glob or -- glob so names with dashes won't become options.

(SC2035)


[warning] 50-54: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 51-51: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 53-53: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 56-60: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 59-59: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 62-82: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 63-63: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 84-93: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 86-86: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 86-86: Quote this to prevent word splitting.

(SC2046)


[warning] 87-87: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 87-87: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (5)
images/openwisp_openvpn/Dockerfile (1)

28-28: ⚡ Quick win

Spelling correction is correct and safe. The change from TOPLOGY_UPDATE_INTERVAL to TOPOLOGY_UPDATE_INTERVAL fixes a typo. No code references the misspelled name, and the correct spelling is already used in openvpn_utils.sh (line 91) where the variable is actually referenced.

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/common/init_command.sh (1)

33-33: LGTM!

Also applies to: 39-39

images/openwisp_openvpn/openvpn.sh (1)

7-7: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

7-7: LGTM!

Also applies to: 10-17

Comment thread images/openwisp_openvpn/openvpn_utils.sh
Comment thread tests/runtests.py
@4f4d 4f4d changed the title [openvpn] Avoided unnecessary CRL restarts #589 [change] Avoid unnecessary CRL restarts when revokelist content is unchanged #589 May 20, 2026
@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from f715d95 to 0340a4c Compare May 20, 2026 05:50
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 125-132: init_send_network_topology currently writes a cron entry
even when TOPOLOGY_UUID or TOPOLOGY_KEY are empty; change the logic so the cron
is only installed when both credentials are present: after loading/exporting
TOPOLOGY_UUID and TOPOLOGY_KEY (symbols TOPOLOGY_UUID, TOPOLOGY_KEY), test that
both are non-empty (e.g. [ -n "$TOPOLOGY_UUID" ] && [ -n "$TOPOLOGY_KEY" ])
before composing the crontab entry that uses TOPOLOGY_UPDATE_INTERVAL and
/send-topology.sh; if either is empty, skip creating the cron and avoid writing
an invalid job.

In `@images/openwisp_openvpn/revokelist.sh`:
- Line 7: The script revokelist.sh uses the Bash-only "source" builtin (e.g.
lines calling source /openvpn_utils.sh), which breaks when /bin/sh is dash/ash;
replace each use of "source" with the POSIX-compliant "." operator (e.g. ".
/openvpn_utils.sh") so the CRL refresh runs under /bin/sh; update every
occurrence of source in revokelist.sh (and any other scripts using source) to
the dot-sourcing form to ensure compatibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1819afc9-76f6-46f1-86cc-1a36a73b4324

📥 Commits

Reviewing files that changed from the base of the PR and between 86f364c and 0340a4c.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/openwisp_openvpn/openvpn.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/revokelist.sh

[warning] 7-7: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-51: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 36-36: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 53-81: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 54-54: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 55-55: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 83-87: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 84-84: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 89-93: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 95-115: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 96-96: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 117-133: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 126-126: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 126-126: Quote this to prevent word splitting.

(SC2046)


[warning] 127-127: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 127-127: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (7)
images/openwisp_openvpn/Dockerfile (1)

28-28: No remaining references to the old variable name exist.

The environment variable name correction from TOPLOGY_UPDATE_INTERVAL to TOPOLOGY_UPDATE_INTERVAL is valid and complete. Verification confirms all references in openvpn_utils.sh already use the corrected spelling, and there are no lingering references to the old misspelled name in the codebase. The variable is also properly documented.

images/openwisp_openvpn/openvpn_utils.sh (1)

3-123: LGTM!

Also applies to: 133-134

images/common/init_command.sh (1)

33-39: LGTM!

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

7-19: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

10-17: LGTM!

tests/runtests.py (1)

7-7: LGTM!

Also applies to: 315-320, 423-527, 530-546

Comment thread images/openwisp_openvpn/openvpn_utils.sh
Comment thread images/openwisp_openvpn/revokelist.sh Outdated
@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (2/3).

@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from 0340a4c to cf0c09c Compare May 20, 2026 06:42
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 62-80: The mv of the downloaded checksum isn't checked so
openvpn_config_download can return success even if mv fails; update the mv
"$tmp_checksum" checksum operation to propagate failure (add || return 1) and
ensure the function uses the existing tmp_checksum/tmp_tar cleanup and trap
logic (symbols: openvpn_config_download, tmp_checksum, tmp_tar, mv
"$tmp_checksum" checksum, trap 'rm -f ...' EXIT HUP INT TERM) so any mv failure
causes the function to return 1.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 53dff560-0432-4cfe-a4f0-868033fe248d

📥 Commits

Reviewing files that changed from the base of the PR and between 0340a4c and cf0c09c.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-51: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 36-36: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 53-81: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 54-54: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 55-55: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 83-87: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 84-84: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 89-93: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 95-115: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 96-96: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 117-137: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 126-126: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 126-126: Quote this to prevent word splitting.

(SC2046)


[warning] 127-127: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 127-127: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (9)
images/openwisp_openvpn/Dockerfile (1)

28-28: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

6-17: LGTM!

tests/runtests.py (3)

7-7: LGTM!

Also applies to: 315-322


423-531: LGTM!


534-551: LGTM!

images/openwisp_openvpn/openvpn_utils.sh (1)

3-51: LGTM!

Also applies to: 83-137

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

6-19: LGTM!

images/common/init_command.sh (1)

33-33: LGTM!

Also applies to: 39-39

Comment thread images/openwisp_openvpn/openvpn_utils.sh Outdated
@4f4d
Copy link
Copy Markdown
Author

4f4d commented May 20, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 106-109: The mv of "$tmp_crl" to revoked.crl is not checked so
failures still return success; modify the block that handles tmp_crl promotion
(the mv "$tmp_crl" revoked.crl call) to check mv's exit status and, on failure,
log an error (or echo to stderr), remove or preserve the tmp file as
appropriate, restore any trap state, and return a non-zero status instead of 0;
ensure you still clear the trap (trap - EXIT HUP INT TERM) only after a
successful mv to avoid reporting a false "changed" state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e696c45d-65b8-4356-9602-6c8c7fe5cc17

📥 Commits

Reviewing files that changed from the base of the PR and between 0340a4c and 2cb8ae6.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-51: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 36-36: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 53-81: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 54-54: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 55-55: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 66-66: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 70-70: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 83-87: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 84-84: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 86-86: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 89-93: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 92-92: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 95-115: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 96-96: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 117-137: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 126-126: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 126-126: Quote this to prevent word splitting.

(SC2046)


[warning] 127-127: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 127-127: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (9)
images/openwisp_openvpn/Dockerfile (1)

28-28: LGTM!

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

6-7: LGTM!

Also applies to: 10-19

images/common/init_command.sh (1)

33-33: LGTM!

Also applies to: 39-39

images/openwisp_openvpn/revokelist.sh (1)

6-17: LGTM!

tests/runtests.py (4)

7-7: LGTM!


315-322: LGTM!


534-551: LGTM!


462-466: The conversion from crl_download_to return code 1 to exit status 2 is correctly implemented.

The crl_download_if_changed function (lines 101–103 in openvpn_utils.sh) already converts the failure return code: when crl_download_to returns 1, the function immediately returns 2. This ensures the test stub's return 1 in fail mode properly triggers the error message assertion, as the calling code in revokelist.sh checks for crl_status -eq 2 to emit the "Failed to download CRL" message.

Comment thread images/openwisp_openvpn/openvpn_utils.sh
@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (2/3).

@4f4d
Copy link
Copy Markdown
Author

4f4d commented May 20, 2026

@coderabbitai review

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (2/3).

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (3/3).

@openwisp-companion
Copy link
Copy Markdown

Commit Message and OpenVPN Failure

Hello @4f4d,
(Analysis for commit ad5c4bd)

Commit Message Failure:
The commit message [openvpn] Propagated CRL promotion failures #589 does not follow the required format. The issue number should be in the footer and indicate if the issue is closed or related.

Fix:
Update the commit message to follow the OpenWISP guidelines. For example:

[openvpn] Fix CRL promotion failures

This commit addresses issues related to the propagation of CRL
failures in the OpenVPN service.

Fixes #589

OpenVPN Container Failure:
The openvpn container failed to start, indicated by the message "optional dependency "openvpn" failed to start: container docker-openwisp-openvpn-1 is unhealthy". This prevented the auto-install.sh script from completing successfully. The logs show that the container is restarting and cannot join the network namespace.

Fix:
This appears to be a transient infrastructure issue. The CI has been restarted automatically. If this issue persists, please investigate the openvpn container logs for more specific errors during its startup sequence.

@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from ad5c4bd to 1ae091b Compare May 20, 2026 08:11
@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from 1ae091b to 595e634 Compare May 20, 2026 08:20
@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (1/3).

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (2/3).

@openwisp-companion
Copy link
Copy Markdown

The CI is failing due to transient infrastructure issues (not related to your code). I have restarted the failed jobs automatically (3/3).

@4f4d 4f4d marked this pull request as ready for review May 20, 2026 09:53
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented May 20, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Incremental Review (Since commit 1cfcac5)

Changes Reviewed

File Change Assessment
images/openwisp_openvpn/openvpn_utils.sh Refactored IPv6 check to use concise if-statement syntax ✅ Correct refactoring

The change converts separate command execution and $? check into a single if cmd >/dev/null 2>&1 expression, which is a standard shell best practice.

Previously Resolved Issues

All 18 previously identified issues remain resolved.

Security & Reliability Highlights

  • Atomic CRL updates - Uses mktemp and atomic mv to prevent partial CRL files
  • Integrity verification - Config downloads are verified against checksums before application
  • Proper cleanup - Trap handlers ensure temp files are cleaned up on all exit paths
  • Fail-fast behavior - Functions return non-zero on failures instead of continuing silently
  • Input validation - TOPOLOGY_UPDATE_INTERVAL validated before creating cron entries
  • Retry resilience - CRL downloads now retry on transient failures

Files Reviewed (1 file)

  • images/openwisp_openvpn/openvpn_utils.sh

The implementation is well-structured, properly tested, and follows security best practices. All review findings have been resolved.


Reviewed by kimi-k2.5-0127 · 86,914 tokens

Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work on this, the CRL part is going in the right direction. I built the OpenVPN image locally, verified /openvpn.crontab loads correctly, and exercised revokelist.sh with controlled CRL contents. Initial/changed CRL restarts OpenVPN, unchanged CRL does not restart, and failed CRL download keeps the existing revoked.crl, which is what we want.

I am requesting changes on the VPN config update path: we need to be stricter about applying downloaded configs and also preserve the useful self-recovery behavior when local state is missing/corrupt.


remote_checksum=$(curl --silent --show-error --fail --insecure \
${API_INTERNAL}/controller/vpn/checksum/$UUID/?key=$KEY) || return 1
if [ -z "$remote_checksum" ] || [ ! -s checksum ]; then
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This treats a missing or empty local checksum the same as a failed remote checksum fetch. I tested the missing-local-checksum case by stubbing the remote checksum to return remote-checksum and leaving local checksum absent. Expected behavior: download the config, update checksum, and restart OpenVPN. Actual behavior: openvpn.sh exits with Failed to fetch or validate OpenVPN checksum, does not download anything, and does not restart.

We must still fail if the remote checksum cannot be downloaded or is empty, but a missing local checksum should mean local state is stale/corrupt and should trigger a safe config re-download.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f543df0

${API_INTERNAL}/controller/vpn/checksum/$UUID/?key=$KEY || return 1
test -s "$tmp_checksum" || return 1

tar xzf "$tmp_tar" || return 1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extracts the downloaded tarball directly into / before verifying the downloaded config against the checksum returned by the API. We need an integrity check before applying anything.

Expected behavior:

- download config and checksum into temporary paths
- verify the downloaded config checksum matches the expected checksum
- only then replace the live files and restart OpenVPN

If config download fails, checksum download fails, checksum is empty, or the downloaded config checksum does not match the API checksum, we must log an error, keep the existing config/checksum untouched, and not restart OpenVPN. Otherwise a partial/corrupted/mismatched config can be applied and later picked up by the next service/container restart.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f543df0


if [ "${OFILE}" != "${NFILE}" ]; then
openvpn_config_download
if ! openvpn_config_download; then
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add coverage for the config integrity path too. The CRL regression test is useful, but we also need to simulate a downloaded config/checksum mismatch and assert that the old config remains in place, checksum remains unchanged, supervisorctl restart openvpn is not called, and an error is logged. I am sorry this was not specified in high detail before.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added config-path regression coverage in tests/runtests.py.

The new test covers:

  • checksum mismatch preserving the existing config/checksum and avoiding restart
  • missing local checksum triggering safe re-download and restart

The updated branch is green.

4f4d added 3 commits May 21, 2026 00:07
Moved OpenVPN-specific helpers into the image directory, made CRL refresh restart OpenVPN only when the CRL changes, and moved the base OpenVPN cron entries into an image-local crontab.

Closes openwisp#589
Preserve self-recovery when the local checksum is missing, verify downloaded OpenVPN config archives against the API checksum before applying them, and add regression coverage for mismatch and recovery cases.

Related to openwisp#589
@4f4d 4f4d force-pushed the issues/589-openvpn-crl-cron branch from f543df0 to 3f1d2a7 Compare May 20, 2026 18:37
@4f4d 4f4d requested a review from nemesifier May 20, 2026 18:45
@nemesifier
Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 126-130: crl_download_to currently does a single curl fetch which
causes crl_download_if_changed to fail on transient errors; modify
crl_download_to to perform multiple attempts with exponential backoff (e.g.,
configurable MAX_ATTEMPTS and initial DELAY, doubling delay each retry) while
still writing to the provided output_path and preserving curl flags (--silent
--show-error --fail --insecure --output). Keep the same function signature,
return non-zero on final failure so callers (crl_download_if_changed) detect
failure, and ensure the final successful attempt exits normally; include brief
comments and use the CA_UUID and DASHBOARD_INTERNAL variables as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 34902685-9f02-4ef4-9502-ad27a3a67963

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3c12a and 3f1d2a7.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-53: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 36-36: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 55-124: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 56-56: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 57-57: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 58-58: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 59-59: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 60-60: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 126-130: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 127-127: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 132-136: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 138-158: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 139-139: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 160-180: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 169-169: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 169-169: Quote this to prevent word splitting.

(SC2046)


[warning] 170-170: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 170-170: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (6)
images/common/init_command.sh (1)

33-33: LGTM!

Also applies to: 39-39

images/openwisp_openvpn/openvpn.sh (1)

6-7: LGTM!

Also applies to: 10-13, 16-19

images/openwisp_openvpn/revokelist.sh (1)

6-7: LGTM!

Also applies to: 10-17

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/Dockerfile (1)

28-28: LGTM!

tests/runtests.py (1)

7-7: LGTM!

Also applies to: 315-316, 318-320, 423-531, 532-678, 681-682, 687-688, 697-697

Comment thread images/openwisp_openvpn/openvpn_utils.sh
Use the same retry and backoff options for the temporary CRL download path that are already used for the direct CRL refresh path.

Related to openwisp#589
@4f4d
Copy link
Copy Markdown
Author

4f4d commented May 20, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 13-14: The separate call to `ip -6 route show default` before `if
[ $? = 0 ]; then` can fail under `set -e` and abort startup; instead, run the
command inside the conditional so failures don't trigger `set -e` (for example
replace the two-step pattern using `ip -6 route show default` and `if [ $? = 0
]; then` with a single conditional that executes the command inside the `if` and
redirects output to /dev/null). Update the usage of `ip -6 route show default`
and the `if [ $? = 0 ]; then` check accordingly so the script safely detects
IPv6 default routes without allowing `set -e` to cause an early exit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9fe58c9c-f81a-45f4-a7f8-8c22dd78cecf

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3c12a and 1cfcac5.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-20: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[style] 14-14: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

(SC2181)


[warning] 22-32: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 30-30: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 30-30: Quote this to prevent word splitting.

(SC2046)


[warning] 34-53: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 36-36: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 39-39: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 55-124: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 56-56: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 57-57: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 58-58: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 59-59: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 60-60: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 75-75: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 79-79: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 126-131: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 127-127: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 130-130: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 130-130: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 133-137: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 136-136: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 136-136: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 139-159: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 140-140: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 161-181: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 170-170: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 170-170: Quote this to prevent word splitting.

(SC2046)


[warning] 171-171: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 171-171: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (6)
images/common/init_command.sh (1)

33-33: LGTM!

Also applies to: 39-39

images/openwisp_openvpn/openvpn.sh (1)

6-7: LGTM!

Also applies to: 10-13, 16-19

images/openwisp_openvpn/revokelist.sh (1)

6-7: LGTM!

Also applies to: 10-17

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/Dockerfile (1)

28-28: LGTM!

tests/runtests.py (1)

7-7: LGTM!

Also applies to: 315-321, 423-678, 681-688, 697-697

Comment thread images/openwisp_openvpn/openvpn_utils.sh Outdated
@4f4d
Copy link
Copy Markdown
Author

4f4d commented May 20, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@images/openwisp_openvpn/openvpn_utils.sh`:
- Around line 125-136: The crl_download function duplicates crl_download_to
(which already defaults output_path to revoked.crl); remove the redundant
crl_download function and update any callers to invoke crl_download_to (or keep
a tiny wrapper that forwards to crl_download_to) so there is a single
implementation. Specifically, delete the crl_download definition from the file
(or replace it with: crl_download() { crl_download_to; }) and ensure callers
referencing crl_download now call crl_download_to (or the new wrapper) to avoid
duplication.
- Around line 21-31: In openvpn_config, the unquoted command substitutions for
UUID, KEY and CA_UUID can be split if Redis values contain whitespace; update
the assignments that call get_redis_value to use quoted substitutions (i.e.,
assign UUID, KEY, CA_UUID from "$(get_redis_value ...)" ) so the results are
treated as single values and exported safely; touch the lines that export UUID,
KEY and CA_UUID in the function openvpn_config to apply this change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 035d3067-477d-47fe-94b0-a7777efe7dae

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3c12a and 2ea0394.

📒 Files selected for processing (8)
  • images/common/init_command.sh
  • images/common/utils.sh
  • images/openwisp_openvpn/Dockerfile
  • images/openwisp_openvpn/openvpn.crontab
  • images/openwisp_openvpn/openvpn.sh
  • images/openwisp_openvpn/openvpn_utils.sh
  • images/openwisp_openvpn/revokelist.sh
  • tests/runtests.py
💤 Files with no reviewable changes (1)
  • images/common/utils.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,html}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/runtests.py
🧠 Learnings (1)
📚 Learning: 2026-02-17T12:50:25.569Z
Learnt from: pandafy
Repo: openwisp/docker-openwisp PR: 564
File: images/common/utils.sh:33-40
Timestamp: 2026-02-17T12:50:25.569Z
Learning: For shell scripts under images/common that invoke certbot, in certbot >= 3.3.0 (Mar 2025), you no longer need --register-unsafely-without-email when using --noninteractive --agree-tos without providing an email. If your scripts previously passed this flag, remove it to rely on default account registration without an email. This applies when no email is supplied; if an email is provided, behavior is unchanged. Update tests to reflect that certbot will proceed without prompting for an email in non-interactive mode.

Applied to files:

  • images/common/init_command.sh
🪛 Shellcheck (0.11.0)
images/common/init_command.sh

[warning] 33-33: In POSIX sh, 'source' in place of '.' is undefined.

(SC3046)

images/openwisp_openvpn/openvpn_utils.sh

[warning] 4-4: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 8-19: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 21-31: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 27-27: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 27-27: Quote this to prevent word splitting.

(SC2046)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)


[warning] 33-52: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 34-34: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 35-35: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 38-38: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 38-38: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 38-38: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 54-123: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 55-55: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 56-56: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 57-57: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 58-58: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 59-59: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 74-74: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 74-74: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 74-74: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 78-78: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 78-78: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 78-78: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 125-130: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 126-126: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 132-136: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 138-158: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 139-139: In POSIX sh, 'local' is undefined.

(SC3043)


[warning] 160-180: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 169-169: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 169-169: Quote this to prevent word splitting.

(SC2046)


[warning] 170-170: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 170-170: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (15)
tests/runtests.py (4)

532-677: Test harness captures inner script exit code incorrectly on mismatch case.

The test expects exit_code=1 for mismatch, but result.exit_code captures the outer sh -lc exit code, not the inner openvpn.sh exit code. Since the command ends after running openvpn.sh without || true, this should propagate correctly. However, if the inner script exits 1, set -eu in the outer script should also cause exit 1.

After re-reading: the outer script has set -eu but the sh {test_dir}/openvpn.sh is the last command, so its exit code propagates. This is correct.


7-7: LGTM!

Also applies to: 315-322


423-530: LGTM!


679-698: LGTM!

images/openwisp_openvpn/openvpn_utils.sh (6)

3-6: LGTM!


8-19: LGTM!


33-52: LGTM!


54-123: LGTM!


138-158: LGTM!


160-180: LGTM!

images/common/init_command.sh (1)

33-39: LGTM!

images/openwisp_openvpn/openvpn.sh (1)

6-21: LGTM!

images/openwisp_openvpn/revokelist.sh (1)

6-17: LGTM!

images/openwisp_openvpn/openvpn.crontab (1)

1-2: LGTM!

images/openwisp_openvpn/Dockerfile (1)

28-28: LGTM!

Comment on lines +21 to +31
function openvpn_config {
# Fectch UUID and Key of the default VPN only if they
# are not already set. The user may override the UUID and Key
# by setting them in the environment variables to use deploy
# a different VPN server.
if [ -z "$UUID" ]; then
export UUID=$(get_redis_value "openwisp_default_vpn_uuid")
export KEY=$(get_redis_value "openwisp_default_vpn_key")
export CA_UUID=$(get_redis_value "openwisp_default_vpn_ca_uuid")
fi
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Unquoted command substitution can break on whitespace in Redis values.

If a Redis value contains spaces or special characters, word splitting will occur. While unlikely for UUIDs/keys, quoting is defensive.

Suggested fix
 function openvpn_config {
 	# Fectch UUID and Key of the default VPN only if they
 	# are not already set. The user may override the UUID and Key
 	# by setting them in the environment variables to use deploy
 	# a different VPN server.
 	if [ -z "$UUID" ]; then
-		export UUID=$(get_redis_value "openwisp_default_vpn_uuid")
-		export KEY=$(get_redis_value "openwisp_default_vpn_key")
-		export CA_UUID=$(get_redis_value "openwisp_default_vpn_ca_uuid")
+		UUID=$(get_redis_value "openwisp_default_vpn_uuid")
+		KEY=$(get_redis_value "openwisp_default_vpn_key")
+		CA_UUID=$(get_redis_value "openwisp_default_vpn_ca_uuid")
+		export UUID KEY CA_UUID
 	fi
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function openvpn_config {
# Fectch UUID and Key of the default VPN only if they
# are not already set. The user may override the UUID and Key
# by setting them in the environment variables to use deploy
# a different VPN server.
if [ -z "$UUID" ]; then
export UUID=$(get_redis_value "openwisp_default_vpn_uuid")
export KEY=$(get_redis_value "openwisp_default_vpn_key")
export CA_UUID=$(get_redis_value "openwisp_default_vpn_ca_uuid")
fi
}
function openvpn_config {
# Fectch UUID and Key of the default VPN only if they
# are not already set. The user may override the UUID and Key
# by setting them in the environment variables to use deploy
# a different VPN server.
if [ -z "$UUID" ]; then
UUID="$(get_redis_value "openwisp_default_vpn_uuid")"
KEY="$(get_redis_value "openwisp_default_vpn_key")"
CA_UUID="$(get_redis_value "openwisp_default_vpn_ca_uuid")"
export UUID KEY CA_UUID
fi
}
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 21-31: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 27-27: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 27-27: Quote this to prevent word splitting.

(SC2046)


[warning] 28-28: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 28-28: Quote this to prevent word splitting.

(SC2046)


[warning] 29-29: Declare and assign separately to avoid masking return values.

(SC2155)


[warning] 29-29: Quote this to prevent word splitting.

(SC2046)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@images/openwisp_openvpn/openvpn_utils.sh` around lines 21 - 31, In
openvpn_config, the unquoted command substitutions for UUID, KEY and CA_UUID can
be split if Redis values contain whitespace; update the assignments that call
get_redis_value to use quoted substitutions (i.e., assign UUID, KEY, CA_UUID
from "$(get_redis_value ...)" ) so the results are treated as single values and
exported safely; touch the lines that export UUID, KEY and CA_UUID in the
function openvpn_config to apply this change.

Comment on lines +125 to +136
function crl_download_to {
local output_path="${1:-revoked.crl}"
curl --silent --show-error --fail --retry 10 --retry-delay 5 --retry-max-time 300 \
--insecure --output "$output_path" \
${DASHBOARD_INTERNAL}/admin/pki/ca/x509/ca/${CA_UUID}.crl
}

function crl_download {
curl --silent --show-error --fail --retry 10 --retry-delay 5 --retry-max-time 300 \
--insecure --output revoked.crl \
${DASHBOARD_INTERNAL}/admin/pki/ca/x509/ca/${CA_UUID}.crl
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

crl_download duplicates crl_download_to with default argument.

crl_download_to already defaults output_path to revoked.crl. The separate crl_download function is redundant.

Suggested consolidation
 function crl_download_to {
 	local output_path="${1:-revoked.crl}"
 	curl --silent --show-error --fail --retry 10 --retry-delay 5 --retry-max-time 300 \
 		--insecure --output "$output_path" \
 		${DASHBOARD_INTERNAL}/admin/pki/ca/x509/ca/${CA_UUID}.crl
 }
 
-function crl_download {
-	curl --silent --show-error --fail --retry 10 --retry-delay 5 --retry-max-time 300 \
-		--insecure --output revoked.crl \
-		${DASHBOARD_INTERNAL}/admin/pki/ca/x509/ca/${CA_UUID}.crl
-}
+# Alias for backward compatibility
+crl_download() { crl_download_to; }
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 125-130: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[warning] 126-126: In POSIX sh, 'local' is undefined.

(SC3043)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 129-129: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 132-136: 'function' keyword is non-standard. Use 'foo()' instead of 'function foo'.

(SC2113)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 135-135: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@images/openwisp_openvpn/openvpn_utils.sh` around lines 125 - 136, The
crl_download function duplicates crl_download_to (which already defaults
output_path to revoked.crl); remove the redundant crl_download function and
update any callers to invoke crl_download_to (or keep a tiny wrapper that
forwards to crl_download_to) so there is a single implementation. Specifically,
delete the crl_download definition from the file (or replace it with:
crl_download() { crl_download_to; }) and ensure callers referencing crl_download
now call crl_download_to (or the new wrapper) to avoid duplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[change] OpenVPN revokelist.sh script seems to needlessly restart OpenVPN

2 participants