]> BookStack Code Mirror - bookstack/commitdiff
Added LDAP group debugging env option
authorDan Brown <redacted>
Wed, 23 Mar 2022 16:34:23 +0000 (16:34 +0000)
committerDan Brown <redacted>
Wed, 23 Mar 2022 16:34:23 +0000 (16:34 +0000)
Closes #3345

app/Auth/Access/Guards/LdapSessionGuard.php
app/Auth/Access/LdapService.php
app/Config/services.php
phpunit.xml
tests/Auth/LdapTest.php

index 5a902af7655aa021b37b9faa1425047f2a258005..18d4c289dbcd00222d04fd210c22b6c6a2dcfd59 100644 (file)
@@ -5,6 +5,7 @@ namespace BookStack\Auth\Access\Guards;
 use BookStack\Auth\Access\LdapService;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\User;
+use BookStack\Exceptions\JsonDebugException;
 use BookStack\Exceptions\LdapException;
 use BookStack\Exceptions\LoginAttemptEmailNeededException;
 use BookStack\Exceptions\LoginAttemptException;
@@ -15,7 +16,7 @@ use Illuminate\Support\Str;
 
 class LdapSessionGuard extends ExternalBaseSessionGuard
 {
-    protected $ldapService;
+    protected LdapService $ldapService;
 
     /**
      * LdapSessionGuard constructor.
@@ -57,12 +58,13 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
      * Attempt to authenticate a user using the given credentials.
      *
      * @param array $credentials
-     * @param bool  $remember
-     *
-     * @throws LoginAttemptException
-     * @throws LdapException
+     * @param bool $remember
      *
      * @return bool
+     * @throws LdapException*@throws \BookStack\Exceptions\JsonDebugException
+     *
+     * @throws LoginAttemptException
+     * @throws JsonDebugException
      */
     public function attempt(array $credentials = [], $remember = false)
     {
index e529b80fdc5129ad326e82567ebb0b0a44a38404..f5d64dab3158d1ddf48dc45377fbe348f90ba6a4 100644 (file)
@@ -15,12 +15,17 @@ use Illuminate\Support\Facades\Log;
  */
 class LdapService
 {
-    protected $ldap;
-    protected $groupSyncService;
+    protected Ldap $ldap;
+    protected GroupSyncService $groupSyncService;
+    protected UserAvatars $userAvatars;
+
+    /**
+     * @var resource
+     */
     protected $ldapConnection;
-    protected $userAvatars;
-    protected $config;
-    protected $enabled;
+
+    protected array $config;
+    protected bool $enabled;
 
     /**
      * LdapService constructor.
@@ -274,6 +279,7 @@ class LdapService
      * Get the groups a user is a part of on ldap.
      *
      * @throws LdapException
+     * @throws JsonDebugException
      */
     public function getUserGroups(string $userName): array
     {
@@ -285,8 +291,17 @@ class LdapService
         }
 
         $userGroups = $this->groupFilter($user);
+        $allGroups = $this->getGroupsRecursive($userGroups, []);
+
+        if ($this->config['dump_user_groups']) {
+            throw new JsonDebugException([
+                'details_from_ldap'  => $user,
+                'parsed_direct_user_groups' => $userGroups,
+                'parsed_recursive_user_groups'  => $allGroups,
+            ]);
+        }
 
-        return $this->getGroupsRecursive($userGroups, []);
+        return $allGroups;
     }
 
     /**
@@ -369,6 +384,7 @@ class LdapService
      * Sync the LDAP groups to the user roles for the current user.
      *
      * @throws LdapException
+     * @throws JsonDebugException
      */
     public function syncGroups(User $user, string $username)
     {
index 2d7253fb81e71edc3c593102003a08ceb98b7bc1..a035f10569500d5c05c552c351e7c5d512117cd3 100644 (file)
@@ -119,6 +119,7 @@ return [
     'ldap' => [
         'server'                 => env('LDAP_SERVER', false),
         'dump_user_details'      => env('LDAP_DUMP_USER_DETAILS', false),
+        'dump_user_groups'       => env('LDAP_DUMP_USER_GROUPS', false),
         'dn'                     => env('LDAP_DN', false),
         'pass'                   => env('LDAP_PASS', false),
         'base_dn'                => env('LDAP_BASE_DN', false),
index 960f4c4c33df441437fe3f678edf70b19a191b62..90320ff41971661f47b2cc4836f5ffa4ada955fb 100644 (file)
@@ -34,6 +34,8 @@
     <server name="AVATAR_URL" value=""/>
     <server name="LDAP_START_TLS" value="false"/>
     <server name="LDAP_VERSION" value="3"/>
+    <server name="LDAP_DUMP_USER_DETAILS" value="false"/>
+    <server name="LDAP_DUMP_USER_GROUPS" value="false"/>
     <server name="SESSION_SECURE_COOKIE" value="null"/>
     <server name="STORAGE_TYPE" value="local"/>
     <server name="STORAGE_ATTACHMENT_TYPE" value="local"/>
index d00e8cf15df4f1de9565967bde4016d6d3b3273f..c59685ef5daadd422ab7d22252092517a3b3ee1a 100644 (file)
@@ -348,6 +348,62 @@ class LdapTest extends TestCase
         ]);
     }
 
+    public function test_dump_user_groups_shows_group_related_details_as_json()
+    {
+        app('config')->set([
+            'services.ldap.user_to_groups'     => true,
+            'services.ldap.group_attribute'    => 'memberOf',
+            'services.ldap.remove_from_groups' => true,
+            'services.ldap.dump_user_groups'   => true,
+        ]);
+
+        $userResp = ['count' => 1, 0 => [
+            'uid'      => [$this->mockUser->name],
+            'cn'       => [$this->mockUser->name],
+            'dn'       => 'dc=test,' . config('services.ldap.base_dn'),
+            'mail'     => [$this->mockUser->email],
+        ]];
+        $this->commonLdapMocks(1, 1, 4, 5, 4, 2);
+        $this->mockLdap->shouldReceive('searchAndGetEntries')->times(4)
+            ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array'))
+            ->andReturn($userResp, ['count' => 1,
+                0 => [
+                    'dn'       => 'dc=test,' . config('services.ldap.base_dn'),
+                    'memberof' => [
+                        'count' => 1,
+                        0       => 'cn=ldaptester,ou=groups,dc=example,dc=com',
+                    ],
+                ],
+            ], [
+                'count' => 1,
+                0 => [
+                    'dn' => 'cn=ldaptester,ou=groups,dc=example,dc=com',
+                    'memberof' => [
+                        'count' => 1,
+                        0       => 'cn=monsters,ou=groups,dc=example,dc=com',
+                    ],
+                ]
+            ], ['count' => 0]);
+
+        $resp = $this->mockUserLogin();
+        $resp->assertJson([
+            'details_from_ldap' => [
+                'dn'       => 'dc=test,' . config('services.ldap.base_dn'),
+                'memberof' => [
+                    0 => 'cn=ldaptester,ou=groups,dc=example,dc=com',
+                    'count' => 1,
+                ]
+            ],
+            'parsed_direct_user_groups' => [
+                'ldaptester',
+            ],
+            'parsed_recursive_user_groups' => [
+                'ldaptester',
+                'monsters',
+            ],
+        ]);
+    }
+
     public function test_external_auth_id_visible_in_roles_page_when_ldap_active()
     {
         $role = Role::factory()->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);