Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased] -
## [unreleased]

### Added

- Manual LDAP to GLPI inventory synchronization from a sync filter, with a dry-run preview and an execute mode (Computer itemtype)
- Fetch all LDAP result pages using paged results (`LDAP_CONTROL_PAGEDRESULTS`), honouring the directory page size configuration
- Flag truncated or failed LDAP searches through an `ldap_complete` completeness signal

### Fixed

- Read the correct `deref_option` field from the LDAP directory configuration
- Prevent JSON injection from LDAP attribute values when building the inventory payload
- Prevent mass assignment when creating an AuthLDAP / SyncFilter relation
68 changes: 68 additions & 0 deletions ajax/syncexecute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/**
* -------------------------------------------------------------------------
* advancedldap plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of advancedldap.
*
* AdvancedLDAP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AdvancedLDAP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AdvancedLDAP. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2018-2023 by Teclib'.
* @license GPLv3+ https://www.gnu.org/licenses/gpl-3.0.html
* @link https://services.glpi-network.com
* -------------------------------------------------------------------------
*/

use Glpi\Exception\Http\BadRequestHttpException;
use GlpiPlugin\Advancedldap\Inventory\LdapSyncExecutor;
use GlpiPlugin\Advancedldap\SyncFilter;

use function Safe\json_encode;
use function Safe\session_write_close;

header('Content-Type: application/json');

Session::checkLoginUser();

$action = $_POST['action'] ?? null;
$raw_syncfilters_id = $_POST['syncfilters_id'] ?? 0;
$syncfilters_id = is_numeric($raw_syncfilters_id) ? (int) $raw_syncfilters_id : 0;

$syncfilter = new SyncFilter();
if ($syncfilters_id <= 0 || !$syncfilter->getFromDB($syncfilters_id)) {
throw new BadRequestHttpException('Invalid SyncFilter');
}

$required_right = ($action === 'execute') ? UPDATE : READ;
$syncfilter->check($syncfilters_id, $required_right);

$executor = new LdapSyncExecutor();

switch ($action) {
case 'execute':
session_write_close();
$results = $executor->executeSingleFilter($syncfilter);
echo json_encode(['success' => true, 'results' => $results]);
break;
case 'dry_run':
$preview = $executor->previewSyncFilter($syncfilter);
echo json_encode(['success' => true, 'preview' => $preview]);
break;
default:
throw new BadRequestHttpException('Unknown action');
}
4 changes: 1 addition & 3 deletions front/authldapsyncfilter.form.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@
if (isset($_POST["add"])) {
$input = $_POST;
$relation->check(-1, CREATE, $input); // @phpstan-ignore argument.type ($_POST keys are always strings)
if ($input !== null) {
$relation->add($input);
}
$relation->add($input); // @phpstan-ignore argument.type ($_POST keys are always strings)
}

Html::back();
3 changes: 3 additions & 0 deletions setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ function plugin_init_advancedldap(): void
/** @var array<string, array<string, string|array<int|string, string>>> $PLUGIN_HOOKS */
global $PLUGIN_HOOKS;

// Note: Hooks::CSRF_COMPLIANT is deprecated since GLPI 11.0 — CSRF is enforced
// automatically by the CheckCsrfListener middleware, so it is intentionally not declared.

$PLUGIN_HOOKS[Hooks::ITEM_PURGE]['advancedldap'] = [
AuthLDAP::class => 'plugin_advancedldap_item_purge',
SyncFilter::class => 'plugin_advancedldap_item_purge',
Expand Down
4 changes: 4 additions & 0 deletions src/AuthLdapSyncFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ public function prepareInputForAdd($input)
return false;
}

$authldap_fk = getForeignKeyFieldForItemType(AuthLDAP::class);
$syncfilter_fk = getForeignKeyFieldForItemType(SyncFilter::class);
$syncfilter_value = $input[$syncfilter_fk] ?? 0;
$syncfilters_id = is_numeric($syncfilter_value) ? (int) $syncfilter_value : 0;
Expand All @@ -380,6 +381,9 @@ public function prepareInputForAdd($input)
$this->deleteExistingLinkForSyncFilter($syncfilters_id);
}

// N'autoriser que les deux clés étrangères de la relation (anti mass-assignment)
$input = array_intersect_key($input, array_flip([$authldap_fk, $syncfilter_fk]));

return parent::prepareInputForAdd($input);
}

Expand Down
Loading