Skip to content

Storage node image/snapin listings come back empty for any caller without a browser session #1312

Description

@mastacontrola

What happens

GET /storagenode/{id} returns empty images and snapinfiles arrays for
every online node when the caller authenticates with an API token instead of a
browser session. The response is a normal 200. Nothing is logged.

The same thing happens inside the server: FOGMulticastManager and anything
else reaching Route::getItem('storagenode', $id) from a CLI daemon gets the
same empty lists.

The browser UI is unaffected, which is why this has not been obvious.

Why

Those two fields are not columns. StorageNode::_getData() builds each one by
making an HTTP request to status/getfiles.php on the node itself, and that
endpoint calls FOGCore::checkAuthAndCSRF().

The only credential FOGURLRequests had to offer was the caller's own PHP
session cookie. session_id() is '' in every CLI daemon and in any API
request authenticated by token, so there was nothing to forward, the inner
request was unauthenticated, and getfiles.php answered 401.

_getData() then does:

return preg_grep(
    '#dev|postdownloadscripts|ssl#',
    json_decode($response[0], true) ?? [],
    PREG_GREP_INVERT
);

json_decode() of the 401 body is not an array, ?? [] turns it into an empty
one, and an authentication failure is served to the caller as "this node has no
images". Wrong data rather than an error.

Two problems, not one

  1. There is no credential a session-less FOG component can present. Fixing
    that is an authentication decision, not a patch to _getData().
  2. Serializing a storage node fans out to that storage node. Every caller
    pays two outbound HTTP requests to a machine that may be down, including the
    many that never read the answer — FOGMulticastManager re-reads its master
    nodes every MULTICASTSLEEPTIME (10s by default), and the storage group grid
    serializes a master node per row. logfiles was already commented out in
    Route::getter() for exactly this cost, which is the tell that the other two
    should be opt-in rather than deleted a third time.

Found while fixing #1308/#1309 (an empty PHPSESSID= cookie minting a
throwaway session on the far side). Stopping that leak did not fix
authentication — it made the 401 honest.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions