From 4d4badf83042ccc6528155acb8a509406886b9ad Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Tue, 17 Aug 2021 14:43:36 -0700 Subject: [PATCH] Got the client-side LDAP setup working well enough for sync! --- app/Http/Controllers/SettingsController.php | 4 ++ app/Models/Ldap.php | 7 ++- app/Models/Setting.php | 48 +++++++++++++++++++ app/Services/LdapAdConfiguration.php | 10 +++- ...d_client_side_l_d_a_p_cert_to_settings.php | 32 +++++++++++++ ...dd_client_side_l_d_a_p_key_to_settings.php | 32 +++++++++++++ resources/lang/en/admin/settings/general.php | 3 ++ resources/views/settings/ldap.blade.php | 30 ++++++++++++ 8 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2021_07_28_031345_add_client_side_l_d_a_p_cert_to_settings.php create mode 100644 database/migrations/2021_07_28_040554_add_client_side_l_d_a_p_key_to_settings.php diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 02a0f2c47..090883b50 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -947,10 +947,14 @@ class SettingsController extends Controller $setting->ldap_jobtitle = $request->input('ldap_jobtitle'); $setting->ldap_country = $request->input('ldap_country'); $setting->ldap_dept = $request->input('ldap_dept'); + $setting->ldap_client_tls_cert = $request->input('ldap_client_tls_cert'); + $setting->ldap_client_tls_key = $request->input('ldap_client_tls_key'); + } if ($setting->save()) { + $setting->update_client_side_cert_files(); return redirect()->route('settings.ldap.index') ->with('success', trans('admin/settings/message.update.success')); } diff --git a/app/Models/Ldap.php b/app/Models/Ldap.php index f06da9058..619f083b0 100644 --- a/app/Models/Ldap.php +++ b/app/Models/Ldap.php @@ -27,7 +27,6 @@ class Ldap extends Model $ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore; $ldap_use_tls = Setting::getSettings()->ldap_tls; - // If we are ignoring the SSL cert we need to setup the environment variable // before we create the connection if ($ldap_server_cert_ignore=='1') { @@ -50,10 +49,16 @@ class Ldap extends Model ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldap_version); ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 20); + if (Setting::getSettings()->ldap_client_tls_cert && Setting::getSettings()->ldap_client_tls_key) { + ldap_set_option($connection, LDAP_OPT_X_TLS_CERTFILE, Setting::get_client_side_cert_path()); + ldap_set_option($connection, LDAP_OPT_X_TLS_KEYFILE, Setting::get_client_side_key_path()); + } + if ($ldap_use_tls=='1') { ldap_start_tls($connection); } + return $connection; } diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 150e290c7..e32ffa64b 100755 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -342,8 +342,56 @@ class Setting extends Model 'is_ad', 'ad_domain', 'ad_append_domain', + 'ldap_client_tls_key', + 'ldap_client_tls_cert' ])->first()->getAttributes(); return collect($ldapSettings); } + + /** + * Return the filename for the client-side SSL cert + * + * @var string + */ + public static function get_client_side_cert_path() + { + return storage_path().'/ldap_client_tls.cert'; + } + + /** + * Return the filename for the client-side SSL key + * + * @var string + */ + public static function get_client_side_key_path() + { + return storage_path().'/ldap_client_tls.key'; + } + + public function update_client_side_cert_files() + { + /** + * I'm not sure if it makes sense to have a cert but no key + * nor vice versa, but for now I'm just leaving it like this. + * + * Also, we could easily set this up with an event handler and + * self::saved() or something like that but there's literally only + * one place where we will do that, so I'll just explicitly call + * this method at that spot instead. It'll be easier to debug and understand. + */ + if($this->ldap_client_tls_cert) { + file_put_contents(self::get_client_side_cert_path(), $this->ldap_client_tls_cert); + } else { + unlink(self::get_client_side_cert_path()); + } + + if($this->ldap_client_tls_key) { + file_put_contents(self::get_client_side_key_path(), $this->ldap_client_tls_key); + } else { + unlink(self::get_client_side_key_path()); + } + } + + } diff --git a/app/Services/LdapAdConfiguration.php b/app/Services/LdapAdConfiguration.php index e9b7e96d4..7a30092b0 100644 --- a/app/Services/LdapAdConfiguration.php +++ b/app/Services/LdapAdConfiguration.php @@ -156,7 +156,7 @@ class LdapAdConfiguration private function setLdapConnectionConfiguration(): array { // Create the configuration array. - return [ + $ldap_settings = [ // Mandatory Configuration Options 'hosts' => $this->getServerUrlBase(), 'base_dn' => $this->ldapSettings['ldap_basedn'], @@ -180,6 +180,14 @@ class LdapAdConfiguration // LDAP_OPT_X_TLS_REQUIRE_CERT => LDAP_OPT_X_TLS_HARD, ], ]; + + if($this->ldapSettings['ldap_client_tls_cert'] || $this->ldapSettings['ldap_client_tls_key']) { + $ldap_settings['custom_options'] = [ + LDAP_OPT_X_TLS_CERTFILE => Setting::get_client_side_cert_path(), + LDAP_OPT_X_TLS_KEYFILE => Setting::get_client_side_key_path() + ]; + } + return $ldap_settings; } /** diff --git a/database/migrations/2021_07_28_031345_add_client_side_l_d_a_p_cert_to_settings.php b/database/migrations/2021_07_28_031345_add_client_side_l_d_a_p_cert_to_settings.php new file mode 100644 index 000000000..aff442cce --- /dev/null +++ b/database/migrations/2021_07_28_031345_add_client_side_l_d_a_p_cert_to_settings.php @@ -0,0 +1,32 @@ +text('ldap_client_tls_cert'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('ldap_client_tls_cert'); + }); + } +} diff --git a/database/migrations/2021_07_28_040554_add_client_side_l_d_a_p_key_to_settings.php b/database/migrations/2021_07_28_040554_add_client_side_l_d_a_p_key_to_settings.php new file mode 100644 index 000000000..1cd9bd363 --- /dev/null +++ b/database/migrations/2021_07_28_040554_add_client_side_l_d_a_p_key_to_settings.php @@ -0,0 +1,32 @@ +text("ldap_client_tls_key"); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn("ldap_client_tls_key"); + }); + } +} diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index e15162210..fe3341eb3 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -61,6 +61,9 @@ return array( 'label_logo' => 'Label Logo', 'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ', 'laravel' => 'Laravel Version', + 'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate', + 'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.', + 'ldap_client_tls_key' => 'LDAP Client-Side TLS key', 'ldap_enabled' => 'LDAP enabled', 'ldap_integration' => 'LDAP Integration', 'ldap_settings' => 'LDAP Settings', diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 61d07a6ad..8abb657e8 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -138,6 +138,36 @@ + +
+
+ {{ Form::label('ldap_client_tls_key', trans('admin/settings/general.ldap_client_tls_key')) }} +
+
+ {{ Form::textarea('ldap_client_tls_key', Request::old('ldap_client_tls_key', $setting->ldap_client_tls_key), ['class' => 'form-control','placeholder' => '-----BEGIN RSA PRIVATE KEY-----'."\r\n1234567890\r\n-----END RSA PRIVATE KEY----- +", $setting->demoMode]) }} + {!! $errors->first('ldap_client_tls_key', '') !!} + @if (config('app.lock_passwords')===true) +

{{ trans('general.feature_disabled') }}

+ @endif +
+
+ + +
+
+ {{ Form::label('ldap_client_tls_cert', trans('admin/settings/general.ldap_client_tls_cert')) }} +
+
+ {{ Form::textarea('ldap_client_tls_cert', Request::old('ldap_client_tls_cert', $setting->ldap_client_tls_cert), ['class' => 'form-control','placeholder' => '-----BEGIN CERTIFICATE-----'."\r\n1234567890\r\n-----END CERTIFICATE-----", $setting->demoMode]) }} +

{{ trans('admin/settings/general.ldap_client_tls_cert_help') }}

+ {!! $errors->first('ldap_client_tls_cert', '') !!} + @if (config('app.lock_passwords')===true) +

{{ trans('general.feature_disabled') }}

+ @endif +
+
+