Author Topic: API: account/udp always returns "Unauthorized action" although accout_upd is gra  (Read 62 times)

0 Members and 3 Guests are viewing this topic.

Offline
*
CWP version: 1.9
OS: AlmaLinux release 8.10 (Cerulean Leopard)
API: external API on port 2304, JSON



Summary

An API key with Account / UPD granted is refused on /v1/account with
action=udp. Every other action on the same key and the same Account function
works. CWP's own debug log shows it resolving the request to accout_upd — the grant
that is switched on — and refusing it anyway, with Unauthorized2 action rather than
the usual Unauthorized action.

Steps to reproduce

1. Create an API key in API Manager. Grant Account ADD, UPD, DEL, LIST, SUSP, UNSP.
2. Call /v1/account with action=list — succeeds.
3. Call /v1/account with action=udp for an existing account — fails.

Code: [Select]
curl -sk https://SERVER:2304/v1/account \
  -d "key=KEY" -d "action=udp" -d "user=USERNAME" \
  -d "email=user@example.com" -d "package=@12" \
  -d "inode=0" -d "openfiles=150" -d "processes=40"

Expected

{"status":"OK"}, with the account's inode / open-file / process limits updated.

Actual

Code: [Select]
{"status":"Error","msj":"Unauthorized action KEY"}

From /var/log/cwp/cwp_api.log (debug=1), key masked

A successful call in the same session — note it ends with a return: clause:

Code: [Select]
2026-08-23 08:09:25  authorized
2026-08-23 08:09:25  Key:<KEY>, action:changepack_udp, ip:<CLIENT> return:{status:OK,format:JSON}
2026-08-23 08:09:25  {status:OK} -> {key:<KEY>,action:udp,user:USERNAME,adds:null,package:8}

The failing call, one second later, same key, same source address:

Code: [Select]
2026-08-23 08:09:26  Unauthorized2 action
2026-08-23 08:09:26  Key:<KEY>, action:accout_upd, ip:<CLIENT>
2026-08-23 08:09:26  Error

Two things stand out:

  • The action it checked is accout_upd — exactly the permission API Manager saves
    for the Account / UPD checkbox (value="accout_upd" in
    mod_reseller_apimanager.html), and exactly the one that is granted.
  • It logs Unauthorized2 action, not Unauthorized action, and the line
    carries no return: clause where every authorised call carries one. That looks like a
    second authorisation check which the grant alone does not satisfy.

Ruled out

  • The grant. Account ADD, UPD, DEL, LIST, SUSP and UNSP are all on in the grid.
  • The key. The same key succeeds in the same second on packages/list
    (pack_list), changepack/udp (changepack_udp) and
    accountdetail/list (detailaccount_list).
  • The request. It matches the Interactive Documentation for account/udp
    field for field: user, email, package with the documented
    @ prefix, inode, openfiles, processes. Omitting
    email produces a different, correct error, so the request is being parsed.
  • A stale saved key. Toggling Account / UPD off, saving, on, saving again changes
    nothing.
  • A missing companion grant. Adding Account Quota / LIST, Quota limit / LIST and
    Metadata Account / LIST changes nothing.
  • The source address. The refused call comes from the same IP as the calls that
    succeed, in the same second.

Impact

account/udp is the only endpoint that sets a per-account inode, open-file or process
limit — Account Quota and Quota limit have no update action, and those three are not package
properties, so packages/add and packages/udp cannot carry them. With this
call refused there is no way to change those limits on an existing account through the API.

This affects my WHMCS module using the endpoint.

Question

Is accout_upd the permission this endpoint actually requires, and what is the second
check that logs Unauthorized2? If the endpoint wants a grant that API Manager does
not expose, that would explain the behaviour.