[WIP] v5 Develop: New LDAP implementation (#6352)

* Fixed missing oauth tables during setup.

* WIP New LDAP implementation

* WIP New LDAP implementation

* WIP New LDAP implementation


Merge remote-tracking branch 'origin/WIP_LDAP' into WIP_LDAP

* WIP New LDAP implementation

Added Adldap2 to handle ldap intergration.

* Updated per PR quality review

* Added specific LDAP settings method

* Corrected version number

* Added return documentation

* Added imports

* Changed class to be injected into controller

* Updated with PR suggestions
This commit is contained in:
Wes Hulette
2018-12-06 17:05:43 -05:00
committed by snipe
parent 3ed2f55696
commit 34246ee4ef
19 changed files with 1509 additions and 956 deletions
+64 -82
View File
@@ -2,106 +2,88 @@
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
use Validator;
use App\Models\Setting;
use Mail;
use App\Notifications\SlackTest;
use Notification;
use App\Notifications\MailTest;
use App\Http\Transformers\LoginAttemptsTransformer;
use DB;
use Mail;
use Validator;
use Notification;
use App\Models\Ldap;
use App\Models\LdapAd;
use App\Models\Setting;
use Illuminate\Http\Request;
use App\Notifications\MailTest;
use App\Notifications\SlackTest;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LoginAttemptsTransformer;
class SettingsController extends Controller
{
public function ldaptest()
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled cannot test.');
/**
* Test the ldap settings
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @param App\Models\LdapAd $ldap
*
* @return \Illuminate\Http\JsonResponse
*/
public function ldapAdSettingsTest(LdapAd $ldap): JsonResponse
{
if($ldap->ldapSettings['ldap_enabled'] === false) {
Log::info('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
\Log::debug('Preparing to test LDAP connection');
// The connect, bind and resulting users message
$message = [];
Log::info('Preparing to test LDAP user login');
// Test user can connect to the LDAP server
try {
$connection = Ldap::connectToLdap();
try {
\Log::debug('attempting to bind to LDAP for LDAP test');
Ldap::bindAdminToLdap($connection);
return response()->json(['message' => 'It worked!'], 200);
} catch (\Exception $e) {
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 600);
$ldap->testLdapAdUserConnection();
$message['login'] = [
'message' => 'Successfully connected to LDAP server.'
];
} catch (\Exception $ex) {
return response()->json([
'message' => 'Error logging into LDAP server, error: ' . $ex->getMessage() . ' - Verify your that your username and password are correct'
], 400);
}
}
public function ldaptestlogin(Request $request)
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled. Cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
$rules = array(
'ldaptest_user' => 'required',
'ldaptest_password' => 'required'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
\Log::debug('LDAP Validation test failed.');
$validation_errors = implode(' ',$validator->errors()->all());
return response()->json(['message' => $validator->errors()->all()], 400);
}
\Log::debug('Preparing to test LDAP login');
Log::info('Preparing to test LDAP bind connection');
// Test user can bind to the LDAP server
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
\Log::debug('Attempting to bind to LDAP for LDAP test');
try {
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
if ($ldap_user) {
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
}
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
} catch (\Exception $e) {
\Log::debug('LDAP login failed');
return response()->json(['message' => $e->getMessage()], 400);
}
} catch (\Exception $e) {
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 500);
$ldap->testLdapAdBindConnection();
$message['bind'] = [
'message' => 'Successfully binded to LDAP server.'
];
} catch (\Exception $ex) {
return response()->json([
'message' => 'Error binding to LDAP server, error: ' . $ex->getMessage()
], 400);
}
Log::info('Preparing to get sample user set from LDAP directory');
// Get a sample of 10 users so user can verify the data is correct
try {
$users = $ldap->testUserImportSync();
$message['user_sync'] = [
'users' => $users
];
} catch (\Exception $ex) {
$message['user_sync'] = [
'message' => 'Error getting users from LDAP directory, error: ' . $ex->getMessage()
];
return response()->json($message, 400);
}
return response()->json($message, 200);
}
public function slacktest()
{
+35 -48
View File
@@ -16,6 +16,7 @@ use Redirect;
use Log;
use View;
use PragmaRX\Google2FA\Google2FA;
use App\Models\LdapAd;
/**
* This controller handles authentication for the user, including local
@@ -39,15 +40,24 @@ class LoginController extends Controller
*/
protected $redirectTo = '/';
/**
* An LdapAd instance
*
* @var \App\Models\LdapAd
*/
protected $ldapAd;
/**
* Create a new authentication controller instance.
*
* @return void
*/
public function __construct()
public function __construct(LdapAd $ldapAd)
{
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
\Session::put('backUrl', \URL::previous());
$this->ldapAd = $ldapAd;
}
function showLoginForm(Request $request)
@@ -64,6 +74,29 @@ class LoginController extends Controller
return view('auth.login');
}
/**
* Log in a user by LDAP
*
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @param Request $request
*
* @return User
*
* @throws Exception
*/
private function loginViaLdap(Request $request): User
{
try {
return $this->ldapAd->ldapLogin($request->input('username'), $request->input('password'));
} catch (\Exception $ex) {
LOG::debug("LDAP user login: " . $ex->getMessage());
throw new \Exception($ex->getMessage());
}
}
private function loginViaRemoteUser(Request $request)
{
$remote_user = $request->server('REMOTE_USER');
@@ -85,53 +118,6 @@ class LoginController extends Controller
}
}
private function loginViaLdap(Request $request)
{
LOG::debug("Binding user to LDAP.");
$ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
if (!$ldap_user) {
LOG::debug("LDAP user ".$request->input('username')." not found in LDAP or could not bind");
throw new \Exception("Could not find user in LDAP directory");
} else {
LOG::debug("LDAP user ".$request->input('username')." successfully bound to LDAP");
}
// Check if the user already exists in the database and was imported via LDAP
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->where('ldap_import', '=', 1)->where('activated', '=', '1')->first();
LOG::debug("Local auth lookup complete");
// The user does not exist in the database. Try to get them from LDAP.
// If user does not exist and authenticates successfully with LDAP we
// will create it on the fly and sign in with default permissions
if (!$user) {
LOG::debug("Local user ".Input::get('username')." does not exist");
LOG::debug("Creating local user ".Input::get('username'));
if ($user = Ldap::createUserFromLdap($ldap_user)) { //this handles passwords on its own
LOG::debug("Local user created.");
} else {
LOG::debug("Could not create local user.");
throw new \Exception("Could not create local user");
}
// If the user exists and they were imported from LDAP already
} else {
LOG::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP.");
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
if (Setting::getSettings()->ldap_pw_sync=='1') {
$user->password = bcrypt($request->input('password'));
}
$user->email = $ldap_attr['email'];
$user->first_name = $ldap_attr['firstname'];
$user->last_name = $ldap_attr['lastname'];
$user->save();
} // End if(!user)
return $user;
}
/**
* Account sign in form processing.
*
@@ -163,6 +149,7 @@ class LoginController extends Controller
if (Setting::getSettings()->ldap_enabled=='1') {
LOG::debug("LDAP is enabled.");
try {
LOG::debug("Attempting to log user in by LDAP authentication.");
$user = $this->loginViaLdap($request);
Auth::login($user, true);
+1 -1
View File
@@ -943,7 +943,7 @@ class SettingsController extends Controller
$setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url');
if ($setting->save()) {
return redirect()->route('settings.index')
return redirect()->route('settings.ldap.index')
->with('success', trans('admin/settings/message.update.success'));
}
@@ -6,25 +6,44 @@ use App\Models\Ldap;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Artisan;
use App\Models\LdapAd;
class LDAPImportController extends Controller
{
/**
* An Ldap instance.
*
* @var LdapAd
*/
protected $ldap;
/**
* Return view for LDAP import
* __construct.
*
* @param LdapAd $ldap
*/
public function __construct(LdapAd $ldap)
{
$this->ldap = $ldap;
}
/**
* Return view for LDAP import.
*
* @author Aladin Alaily
* @since [v1.8]
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @return \Illuminate\Contracts\View\View
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create()
{
$this->authorize('update', User::class);
try {
$ldapconn = Ldap::connectToLdap();
Ldap::bindAdminToLdap($ldapconn);
$this->ldap->testLdapAdUserConnection();
} catch (\Exception $e) {
return redirect()->route('users.index')->with('error', $e->getMessage());
}
@@ -32,19 +51,21 @@ class LDAPImportController extends Controller
return view('users/ldap');
}
/**
* LDAP form processing.
*
* @author Aladin Alaily
* @since [v1.8]
* @author Wes Hulette <jwhulette@gmail.com>
*
* @since 5.0.0
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
// Call Artisan LDAP import command.
$location_id = $request->input('location_id');
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
Artisan::call('snipeit:ldapAd-sync', ['--location_id' => $location_id, '--json_summary' => true]);
// Collect and parse JSON summary.
$ldap_results_json = Artisan::output();
@@ -54,8 +75,9 @@ class LDAPImportController extends Controller
if ($ldap_results['error']) {
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
}
return redirect()->route('ldap/user')
->with('success', "LDAP Import successful.")
->with('success', 'LDAP Import successful.')
->with('summary', $ldap_results['summary']);
}
}