Conversation
* Add dns_cpanel_uapi.sh
There was a problem hiding this comment.
Pull request overview
Adds a new DNS API hook for managing ACME DNS-01 TXT records via the cPanel UAPI, and updates the container base image used by the project’s Docker build.
Changes:
- Introduce
dnsapi/dns_cpanel_uapi.shimplementingdns_cpanel_uapi_add/dns_cpanel_uapi_rmusing cPanel UAPI endpoints. - Add support for an optional
cPanel_TTLsetting (defaulting to 120 seconds) for created TXT records. - Bump Docker base image from Alpine 3.22 to 3.23.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| dnsapi/dns_cpanel_uapi.sh | New DNS hook to add/remove TXT records via cPanel UAPI (mass_edit_zone/parse_zone). |
| Dockerfile | Updates Alpine base image version used for the Docker build. |
| if ! _cpanel_uapi_request "execute/DNS/parse_zone?zone=${_zone}"; then | ||
| _err "Request to parse zone failed for $_zone" | ||
| return 1 | ||
| fi | ||
|
|
||
| # Split JSON records onto separate lines using a POSIX-portable sed literal newline | ||
| # (\\n in sed replacement is a GNU/BusyBox extension; a backslash-newline works everywhere) | ||
| _soa_line=$(echo "$_result" | sed 's/},{/},\ | ||
| {/g' | grep '"record_type":"SOA"' | _head_n 1) | ||
| _debug "SOA line: $_soa_line" | ||
|
|
||
| if [ -z "$_soa_line" ]; then | ||
| _err "SOA record not found for zone $_zone" | ||
| _debug "parse_zone response: $_result" | ||
| return 1 | ||
| fi |
There was a problem hiding this comment.
After execute/DNS/parse_zone, the code proceeds to parse records without validating the UAPI response status. If the API returns a JSON error with "status":0, this will surface as “SOA record not found” instead of the real failure reason. Check for "status":1 (and log the error message/response) before attempting to extract the SOA serial.
| if ! _cpanel_uapi_request "execute/DNS/parse_zone?zone=${_domain}"; then | ||
| _err "Request to parse zone failed for $_domain" | ||
| return 1 | ||
| fi |
There was a problem hiding this comment.
_cpanel_uapi_findentry treats any parse_zone response as valid and returns “entry doesn't exist” when no match is found. If parse_zone actually failed (e.g., "status":0), this silently turns an API error into a no-op delete. Validate "status":1 after the request and return an error when the API indicates failure.
| export _H1="Authorization: cpanel $cPanel_Username:$cPanel_Apitoken" | ||
| _result=$(_get "$cPanel_Hostname/$1") | ||
| return $? |
There was a problem hiding this comment.
_cpanel_uapi_request sets export _H1=... but never restores/unsets it. Since acme.sh always passes $_H1..$_H5 on every subsequent _get/_post call, this can leak the cPanel Authorization header to unrelated HTTP requests later in the run. Save the previous header values (at least _H1, ideally _H1.._H5) before setting them and restore/unset them after the request (even on failure).
| export _H1="Authorization: cpanel $cPanel_Username:$cPanel_Apitoken" | |
| _result=$(_get "$cPanel_Hostname/$1") | |
| return $? | |
| _cpanel_uapi_old_H1=$_H1 | |
| _cpanel_uapi_old_H2=$_H2 | |
| _cpanel_uapi_old_H3=$_H3 | |
| _cpanel_uapi_old_H4=$_H4 | |
| _cpanel_uapi_old_H5=$_H5 | |
| if [ "${_H1+set}" = "set" ]; then | |
| _cpanel_uapi_had_H1=1 | |
| else | |
| _cpanel_uapi_had_H1= | |
| fi | |
| if [ "${_H2+set}" = "set" ]; then | |
| _cpanel_uapi_had_H2=1 | |
| else | |
| _cpanel_uapi_had_H2= | |
| fi | |
| if [ "${_H3+set}" = "set" ]; then | |
| _cpanel_uapi_had_H3=1 | |
| else | |
| _cpanel_uapi_had_H3= | |
| fi | |
| if [ "${_H4+set}" = "set" ]; then | |
| _cpanel_uapi_had_H4=1 | |
| else | |
| _cpanel_uapi_had_H4= | |
| fi | |
| if [ "${_H5+set}" = "set" ]; then | |
| _cpanel_uapi_had_H5=1 | |
| else | |
| _cpanel_uapi_had_H5= | |
| fi | |
| export _H1="Authorization: cpanel $cPanel_Username:$cPanel_Apitoken" | |
| _result=$(_get "$cPanel_Hostname/$1") | |
| _cpanel_uapi_status=$? | |
| if [ -n "$_cpanel_uapi_had_H1" ]; then | |
| _H1=$_cpanel_uapi_old_H1 | |
| else | |
| unset _H1 | |
| fi | |
| if [ -n "$_cpanel_uapi_had_H2" ]; then | |
| _H2=$_cpanel_uapi_old_H2 | |
| else | |
| unset _H2 | |
| fi | |
| if [ -n "$_cpanel_uapi_had_H3" ]; then | |
| _H3=$_cpanel_uapi_old_H3 | |
| else | |
| unset _H3 | |
| fi | |
| if [ -n "$_cpanel_uapi_had_H4" ]; then | |
| _H4=$_cpanel_uapi_old_H4 | |
| else | |
| unset _H4 | |
| fi | |
| if [ -n "$_cpanel_uapi_had_H5" ]; then | |
| _H5=$_cpanel_uapi_old_H5 | |
| else | |
| unset _H5 | |
| fi | |
| unset _cpanel_uapi_old_H1 _cpanel_uapi_old_H2 _cpanel_uapi_old_H3 _cpanel_uapi_old_H4 _cpanel_uapi_old_H5 | |
| unset _cpanel_uapi_had_H1 _cpanel_uapi_had_H2 _cpanel_uapi_had_H3 _cpanel_uapi_had_H4 _cpanel_uapi_had_H5 | |
| return "$_cpanel_uapi_status" |
sync