Zabbix v7 et le point d'API user.login comme en v6

Dans la version 7 de Zabbix, il y a de nombreux changements. Certains cassent la compatibilité, et celui qui m’intéresse dans ce billet concerne le point d’API user.login.

En effet, depuis la v6, le paramètre user est déprécié, et a été supprimé en v7 au profit de username (déjà présent en v6 pour préparer).

Si vous utilisez déjà les jetons pour vos appels API, ou ce nouveau paramètre, vous n’aurez aucun impact. Mais si vous trainez de vieux script, vous, ou des partenaires, qui utilisent la méthode user.login et le paramètre user, vous allez vous retrouver avec des scripts qui ne fonctionnent plus.

La solution est simple : corriger ces scripts. Mais si ce n’est pas possible immédiatement ?


Avertissement :

La solution proposée ici est sale à mes yeux, mais permettra aux scripts utilisant l’ancienne méthode de continuer à fonctionner. Le temps de les mettre à jour.

Cette solution est bien à considérer comme temporaire, car elle sera écrasée à votre prochaine mise à jour. Sauf si vous la remettez manuellement en place après coup.

Forcez les partenaires à mettre leurs scripts à jour !


Pour proposer de nouveau temporairement l’accès au paramètre user, ça va se passer dans le fichier include/classes/api/services/CUser.php à la ligne 2051. Cherchez la fonction login(array $data) :

/**
    * @param array $data
    *
    * @return string|array
    */

public function login(array $data) {
    $api_input_rules = ['type' => API_OBJECT, 'fields' => [
        'username' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'password' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'userData' =>   ['type' => API_FLAG]
    ]];

    if (!CApiInputValidator::validate($api_input_rules, $data, '/', $error)) {
        self::exception(ZBX_API_ERROR_PARAMETERS, $error);
    }

$db_users = self::findLoginUsersByUsername($data['username']);
// ... snip ...

En v6, c’était (même fichier, mais ligne 1512) :

/**
    * @param array $data
    *
    * @return string|array
    */

public function login(array $data) {
    $api_input_rules = ['type' => API_OBJECT, 'fields' => [
        'username' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'user' =>       ['type' => API_STRING_UTF8, 'flags' => API_DEPRECATED, 'length' => 255],
        'password' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'userData' =>   ['type' => API_FLAG]
    ]];

    if (array_key_exists('user', $user)) {
        if (array_key_exists('username', $user)) {
            self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'user'));
        }
        $user['username'] = $user['user'];
    }

    if (!CApiInputValidator::validate($api_input_rules, $user, '/', $error)) {
        self::exception(ZBX_API_ERROR_PARAMETERS, $error);
    }

// ... snip ...

Comme documenté et attendu, la différence se joue sur la disparition du paramètre user. Il faut donc, pour la v7, remettre dans la variable $api_input_rules la ligne le déclarant :

'user' =>       ['type' => API_STRING_UTF8, 'flags' => API_DEPRECATED, 'length' => 255],

Et reprendre le mapping qui met la valeur de user dans username (mais il faudra changer $user en $data):

if (array_key_exists('user', $user)) {
    if (array_key_exists('username', $user)) {
        self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'user'));
    }
    $user['username'] = $user['user'];
}

Et donc la fonction v7 avec la rustine :

/**
    * @param array $data
    *
    * @return string|array
    */

public function login(array $data) {
    $api_input_rules = ['type' => API_OBJECT, 'fields' => [
        'user' =>       ['type' => API_STRING_UTF8, 'flags' => API_DEPRECATED, 'length' => 255], // FIX Compat v6
        'username' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'password' =>   ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => 255],
        'userData' =>   ['type' => API_FLAG]
    ]];

    // FIX Compat v6
    if (array_key_exists('user', $data)) {
        if (array_key_exists('username', $data)) {
            self::exception(ZBX_API_ERROR_PARAMETERS, _s('Parameter "%1$s" is deprecated.', 'user'));
        }
        $data['username'] = $data['user'];
    } // ---- END FIX

    if (!CApiInputValidator::validate($api_input_rules, $data, '/', $error)) {
        self::exception(ZBX_API_ERROR_PARAMETERS, $error);
    }

$db_users = self::findLoginUsersByUsername($data['username']);
// ... snip ...

Et voilà. L’appli ou le script historique fonctionne à nouveau.

Comme dit plus haut, il s’agit d’une rustine qui ne doit pas être considérée comme définitive !

Lien