API Connect

 View Only

Patching the login_security module to work with IBM API Connect portal site

By Saber Hamidi posted Mon April 22, 2024 08:53 AM

  

Introduction

Starting with releases 10.0.5.8 and 10.0.8, we will no longer include the login_security module as part of our default package. This decision comes after receiving ongoing feedback from customers regarding issues with this module. Although it's no longer part of our standard releases, we recognise that many customers may still use it by installing it as a custom module. In this blog post, we will provide you with instructions on how to patch the login_security module for compatibility with the IBM API Connect portal without compromising your site's functionality. Please note that these patches will only fix the issues that have been reported to us so far, and you may still experience some functionalities of that module not working as expected, in which case we will not provide any further patches or support. 

Warning: Since the login_security module is no longer part of our standard distribution, anyone who decides to use it as a custom module does so at their own risk. IBM will not offer support for this module, and you will be responsible for all maintenance and troubleshooting.

Installation

To install the login_security module on your site, you can download its latest version for Drupal 10 from here. For detailed guidance on how to install a custom module, refer to our step-by-step tutorial page on our Knowledge Center.

By following these instructions, you should be able to use the login_security module on your site without affecting its stability. However, be aware that further updates, support, or compatibility fixes for this module are not guaranteed. 

Patching

After installing the module you can now patch it to make it work with the IBM API Connect Portal site. 

1: First exec into one of portal-www pods admin container;

Command: kubectl exec -ti POD_NAME -c admin -- bash

2: Create the first patch files 

Command: vi /tmp/login_security-patch-1.patch

Then copy and paste below into the newly created file, then save and exit (:wq).

--- modules/login_security/login_security.module    2023-01-03 14:21:29
+++ modules/login_security/login_security.module    2024-04-12 16:34:44
@@ -11,6 +11,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Component\Render\FormattableMarkup;
+use Drupal\ibm_apim\ApicType\ApicUser;
 
 /**
  * Implements hook_cron().
@@ -124,7 +125,16 @@
 function login_security_soft_block_validate(array $form, FormStateInterface $form_state) {
   $config = \Drupal::config('login_security.settings');
 
-  $variables = _login_security_get_variables_by_name($form_state->getValue('name'));
+  $name = !empty($form_state->getValue('name')) ? $form_state->getValue('name') : NULL;
+  if ($name) {
+    $variables = _login_security_get_variables_by_name($name, $form_state->getValue('registry_url'));
+  }
+  else {
+    // Set as already notified:
+    \Drupal::state()->set('login_security.threshold_notified', TRUE);
+  }
+
+
   // Check for host login attempts: Soft.
   if ($variables['@soft_block_attempts'] >= 1) {
     if ($variables['@ip_current_count'] >= $variables['@soft_block_attempts']) {
@@ -145,12 +155,19 @@
   // Sanitize user input.
   // Setting $name=NULL will use the anonymous user:
   $name = !empty($form_state->getValue('name')) ? $form_state->getValue('name') : NULL;
+  $registry_url = !empty($form_state->getValue('registry_url')) ? $form_state->getValue('registry_url') : NULL;
 
   // Expire old tracked entries.
   _login_security_remove_events();
 
-  // Populate variables to be used in any module message or login operation.
-  $variables = _login_security_get_variables_by_name($name);
+  if ($name) {
+    // Populate variables to be used in any module message or login operation.
+    $variables = _login_security_get_variables_by_name($name, $registry_url);
+  }
+  else {
+    // Set as already notified:
+    \Drupal::state()->set('login_security.threshold_notified', TRUE);
+  }
 
   // Detect an ongoing attack:
   // An ongoing attack counts the total failed login attempts and notifies
@@ -436,22 +453,31 @@
  * @return array
  *   login_security variables.
  */
-function _login_security_get_variables_by_name($name = NULL) {
+function _login_security_get_variables_by_name($name = NULL, $registry = NULL) {
   global $base_url;
 
   $config = \Drupal::config('login_security.settings');
-  $account = _login_security_user_load_by_name($name);
+  $apicUserStorage = \Drupal::service('ibm_apim.user_storage');
+  if ($registry !== NULL) {
+    $login_user = new ApicUser();
+    $login_user->setUsername($name);
+    $login_user->setApicUserRegistryUrl($registry);
+    $account = $apicUserStorage->load($login_user);
+  } else {
+    // fall through to the more risky user_load_by_name - this will fail if there are more than 1 matching user by name
+    $account = user_load_by_name($name);
+  }
   $ipaddress = \Drupal::request()->getClientIp();
   $request_time = \Drupal::time()->getRequestTime();
   $variables = [
     '@date' => \Drupal::service('date.formatter')->format($request_time),
     '@ip' => $ipaddress,
-    '@username' => $account->getAccountName(),
-    '@email' => $account->getEmail() ?? '',
-    '@uid' => $account->id(),
+    '@username' => $account ? $account->getAccountName() : null, 
+    '@email' => $account ? $account->getEmail() : null,
+    '@uid' => $account ? $account->id() : null,
     '@site' => \Drupal::config('system.site')->get('name'),
     '@uri' => $base_url,
-    '@edit_uri' => Url::fromRoute('entity.user.edit_form', ['user' => $account->id()], ['absolute' => TRUE])->toString(),
+    '@edit_uri' => $account ? Url::fromRoute('entity.user.edit_form', ['user' => $account->id()], ['absolute' => TRUE])->toString() : null,
     '@hard_block_attempts' => $config->get('host_wrong_count_hard'),
     '@soft_block_attempts' => $config->get('host_wrong_count'),
     '@user_block_attempts' => $config->get('user_wrong_count'),

3: Create the second patch files 

Command: vi /tmp/login_security-patch-2.patch

Then copy and paste below into the newly created file, then save and exit (:wq).

--- modules/login_security/src/Form/LoginSecurityAdminSettings.php    2023-01-03 14:21:29
+++ modules/login_security/src/Form/LoginSecurityAdminSettings.php    2024-03-28 16:27:56
@@ -90,6 +90,7 @@
     ];
     $form['notification']['disable_core_login_error'] = [
       '#type' => 'checkbox',
+      '#disabled' => TRUE,
       '#title' => $this->t('Disable login failure error message'),
       '#description' => $this->t('Prevents the display of login error messages. <br>
         A user attempting to login will not be aware if the account exists, an invalid user name or password has been submitted, or if the account is blocked. The core messages are also hidden.'),
@@ -97,6 +98,7 @@
     ];
     $form['notification']['notice_attempts_available'] = [
       '#type' => 'checkbox',
+      '#disabled' => TRUE,
       '#title' => $this->t('Notify the user about the number of remaining login attempts'),
       '#default_value' => $config->get('notice_attempts_available'),
       '#description' => $this->t('The user is notified about the number of remaining login attempts before the account gets blocked. <br>

4: Apply the patches

First CD into your site directory 

Command: cd /var/aegir/platforms/PLATFORM-DIR-NAME/sites/SITE-DIR-NAME               

Please note that you can get your platform directory name by running ls /var/aegir/platforms and you can get your site directory name by running list_sites -a | awk '{print $3}'

Once on the site directory, you can then run the patch command to patch the module.

Command:  patch -p0 -i /tmp/login_security-patch-1.patch    You can run a dry run of this command first by providing the --dry-run flag to the command.

Repeat the above command for the second patch file. 

Once the patches are applied you can enable the module and start configuring it.

#APIConnect #developerportal #portal #drupal


#Highlights-home
0 comments
15 views

Permalink