Hauptmenü

Anbindung Active Directory

Begonnen von Torsten Thau, 31.10.2019 21:06:37

⏪ vorheriges - nächstes ⏩

Torsten Thau

In KIX ist es möglich ein Active Directory (oder andere per LDAP ansprechbare Verzeichnisdienste) anzubinden. Dabei wird zwischen folgenden Funktionen unterschieden:

       
  • (1) Agentennutzer (zur Authentifizierung, als Datenbackend und zur Autorisierung in Verbindung mit Rollenberechtigungen)
  • (2) Kundennutzer (als Datenbackend und zur Authentifizierung)
Die nachfolgenden Konfigurationen setzen voraus, dass das Active Directory über den LDAP-Port 389 erreichbar ist. Sollte LDAP via SSL benutzt werden , sind die Angaben unter "Params" zu aktivieren und der korrekte Port (meist 636) einzutragen. Wird der sog. "Global Catalog" des AD verwendet, muss Port 3268 bzw. 3269 (SSL) eingetragen werden.

(1) AD für Agentennutzer

Im folgenden Beispiel wird ein AD zur Authentifizierung von Agentennutzern verwendet. Die Abschnitte der Konfiguration sind in der Datei /opt/kix/Kernel/Config.pm innerhalb der Funktion "Load" zu ergänzen.


    # authentication config - just asks if login+password proves identity of the user...
    $Self->{'AuthModule'}               = 'Kernel::System::Auth::LDAP';
    $Self->{'AuthModule::LDAP::Host'}   = ['ad1.intern.companyx.de'];
    $Self->{'AuthModule::LDAP::BaseDN'} = 'DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthModule::LDAP::UID'}    = 'sAMAccountName';
    $Self->{'AuthModule::LDAP::GroupDN'}    = 'CN=Helpdesk-Agenten,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthModule::LDAP::AccessAttr'} = 'member';
    #$Self->{'AuthModule::LDAP::UserAttr'} = 'UID';
    #$Self->{'AuthModule::LDAP::UserAttr'} = 'DN';
    $Self->{'AuthModule::LDAP::SearchUserDN'} = 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthModule::LDAP::SearchUserPw'} = 'xxxxxxxxxx';
    $Self->{'AuthModule::LDAP::AlwaysFilter'} = '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';
    #$Self->{'AuthModule::LDAP::UserSuffix'} = '@domain.com';
    #$Self->{'AuthModule::LDAP::UserLowerCase'} = 0;
    #$Self->{'AuthModule::LDAP::Charset'} = 'iso-8859-1';
    #$Self->{'AuthModule::LDAP::Params'} = {
    #    port    => 389,
    #    timeout => 120,
    #    async   => 0,
    #    version => 3,
    #};
    $Self->{'AuthModule::LDAP::Die'} = 1;


Damit allein wird nur geprüft ob der anmeldende Nutzer der ist, der er vorgibt zu sein. Es wird vorausgesetzt, dass der Nutzer im KIX bereits bekannt und vorhanden ist (unter dem gleichen Login-Namen).

Soll nun  bei erfolgreicher Anmeldung ein Agent erstmalig angelegt bzw. die hinterlegten Daten mit denen aus dem AD aktualisiert werden, wird noch eine "AuthSync"-Konfiguration benötigt. Diese verwendet meistens die gleichen Parameterwerte. Das obige Beispiel fortgesetzt sieht dann wie folgt aus:


    #---------------------------------------------------------------------------
    # data synchronisation config - mostly just copies Auth-configuration...
    $Self->{'AuthSyncModule'}               = 'Kernel::System::Auth::Sync::LDAP';
    $Self->{'AuthSyncModule::LDAP::Host'}   = ['ad1.intern.companyx.de'];
    $Self->{'AuthSyncModule::LDAP::BaseDN'} = 'DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthSyncModule::LDAP::UID'}    = 'sAMAccountName';
    $Self->{'AuthSyncModule::LDAP::GroupDN'}= 'CN=Helpdesk-Agenten,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthSyncModule::LDAP::AccessAttr'} = 'member';
    $Self->{'AuthSyncModule::LDAP::SearchUserDN'} = 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
    $Self->{'AuthSyncModule::LDAP::SearchUserPw'} = 'xxxxxxxxxx';
   
    # this filters inactive and locked AD-accounts
    $Self->{'AuthSyncModule::LDAP::AlwaysFilter'} = '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';


    #$Self->{'AuthSyncModule::LDAP::Charset'} = 'iso-8859-1';
    #$Self->{'AuthSyncModule::LDAP::Params'} = {
    #    port    => 389,
    #    timeout => 120,
    #    async   => 0,
    #    version => 3,
    #};


    # mapping AD attribute => KIX user attribute
    $Self->{'AuthSyncModule::LDAP::UserSyncMap'} = {
        UserFirstname => 'givenName',
        UserLastname  => 'sn',
        UserEmail     => 'mail',
    };
    $Self->{'AuthSyncModule::LDAP::Die'} = 1;


Möchte man nun noch die Zuordnung der in KIX konfigurierten Rollen autom. bei Anmeldung vornehmen, bietet sich an dies auf Basis von AD-Gruppen-Mitgliedschaften abzubilden. Dabei empfiehlt es sich für jede Rolle in KIX eine AD-Gruppe zu verwenden. Die Verwendung von geschachtelten AD-Gruppen ("nested groups") ist nicht ohne Weiteres möglich. Zur Zuordnung von AD-Gruppen zu KIX-Rollen wird folgende Konfiguration ergänzt:


    #---------------------------------------------------------------------------
    # authorisation by mapping AD group => KIX role...
    # (requires KIX roles to be defined within KIX)
    $Self->{'AuthSyncModule::LDAP::UserSyncRolesDefinition'} = {


        # if user is member of AD-group, then KIX role "R_CMDBMaintainer" is assigned on each login...
        'CN=CMDBMaintainer,OU=Helpdesk,DC=intern,DC=CompanyX,DC=de'=> {
            'R_CMDBMaintainer' => 1,
            },
        'CN=Support,OU=Helpdesk,DC=intern,DC=CompanyX,DC=de' => {
            'R_Support' => 1,
        },
        'CN=Purchasing,OU=Helpdesk,DC=intern,DC=CompanyX,DC=de' => {
            'R_Purchasing' => 1,
         },
     }; 


Soll sich der Systemnutzer (der selten im AD abgelegt wird) noch anmelden können, ist es erforderlich die KIX-DB selbst als niedrig priorisiertes Auth.-Backend zu hinterlegen. Dazu kann folgender Abschnitt in der Config.pm ergänzt werden:


  $Self->{AuthModule9} = 'Kernel::System::Auth::DB';



(2) AD für Kundennutzer

Häufig wird das Active Directory genutzt um Daten zu Kontenkontakten in KIX bereit zu stellen. Die folgende Konfiguration erlaubt die direkte Nutzung von im AD vorhandenen Einträgen im KIX. Es findet dabei keine Synchronisation statt (!). Sobald ein Eintrag im AD nicht mehr vorhanden ist, stehen die Daten in KIX nicht mehr zur Verfügung. Dies ist zu beachten wenn Mitarbeiter aus der Organisation ausscheiden, Zuordnungen oder gar der Identifikator (im Beispiel "sAMAccountName") geändert wird (bspw. nach Heirat).

Im folgenden Beispiel werden Personeneinträge, bei denen das Attribut "departmentNumber" gesetzt ist, als Kundennutzer eingebunden. Dabei wird die "departmentNumber" als Kundennummer (Identifikator der Kundenorganisation/-gruppe) verwendet:


  $Self->{'CustomerUser'} = {
      Name   => 'LDAP Backend',
      Module => 'Kernel::System::CustomerUser::LDAP',
      Params => {
          Host   => ['ad1.intern.companyx.de'],
          BaseDN => 'DC=intern,DC=CompanyX,DC=de',
          SSCOPE => 'sub',
          UserDN => 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de',
          UserPw => 'xxxxxxxxxx',
          AlwaysFilter => '(&(objectClass=user)(departmentNumber=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))',
          SourceCharset => 'utf-8',
          DestCharset   => 'utf-8',
          Die           => 0,
          Params        => {
              port    => 389,
              timeout => 120,
              async   => 0,
              version => 3,
          },
      },
      CustomerKey            => 'sAMAccountName',
      CustomerID             => 'departmentNumber',
      CustomerUserListFields => [ 'sn', 'givenname', 'departmentNumber', 'mail' ],
      CustomerUserSearchFields => [ 'sAMAccountName', 'sn', 'givenname', 'mail', 'departmentNumber' ],
      CustomerUserSearchPrefix             => '*',
      CustomerUserSearchSuffix             => '*',
      CustomerUserSearchListLimit          => 250,
      CustomerUserPostMasterSearchFields   => ['mail'],
      CustomerUserNameFields               => [ 'givenname', 'sn' ],
      CustomerUserExcludePrimaryCustomerID => 0,
      #CustomerUserValidFilter => '(!(description=gesperrt))',
      #AdminSetPreferences => 0,
      CustomerCompanySupportPersonalCustomerID => 1,


      # caching might speed up your KIX significantly, but may provide obsolete data for TTL
      CacheTTL => 3600,
      Map      => [
          # note: Login, Email and CustomerID needed!
          # var, frontend, storage, shown (1=always,2=lite), required, storage-type, http-link, readonly
          [ 'UserPosition',    'Position',     'title',                      1, 0, 'var', '', 0 ],
          [ 'UserSalutation',  'Salutation',   'physicalDeliveryOfficeName', 1, 0, 'var', '', 0 ],
          [ 'UserTitle',       'Title',        'employeeType',               1, 0, 'var', '', 0 ],
          [ 'UserFirstname',   'Firstname',    'givenname',                  1, 1, 'var', '', 0 ],
          [ 'UserLastname',    'Lastname',     'sn',                         1, 1, 'var', '', 0 ],
          [ 'UserLogin',       'Username',     'sAMAccountName',             1, 1, 'var', '', 0 ],
          [ 'UserEmail',       'Email',        'mail',                       1, 1, 'var', '', 0 ],
          [ 'UserCustomerID',  'CustomerID',   'departmentNumber',           1, 1, 'var', '', 0 ],
          [ 'UserDepartment1', 'Department 1', 'division',                   1, 0, 'var', '', 0 ],
          [ 'UserDepartment2', 'Department 2', 'department',                 1, 0, 'var', '', 0 ],
          [ 'UserCompany',     'Company',      'company',                    1, 0, 'var', '', 0 ],
          [ 'UserPhone',       'Phone',        'telephonenumber',            1, 0, 'var', '', 0 ],
          [ 'UserAddress',     'Address',      'postaladdress',              1, 0, 'var', '', 0 ],
          [ 'UserRoom',        'Room',         'roomNumber',                 1, 0, 'var', '', 0 ],
          [ 'UserEmployeeID',  'Personalnr.',  'employeeID',                 1, 0, 'var', '', 0 ],
          [ 'UserComment',     'Comment',      'description',                1, 0, 'var', '', 0 ],
      ],
  };


Sofern die Kundenkontakte auch das Kundenportal von KIX nutzen können, ist es häufig gewünscht, dass diese das aus Ihrem AD bekannte Nutzerpasswort verwenden können sollen. Dazu wird obige Konfiguration wie folgt ergänzt.


  $Self->{'Customer::AuthModule'}               = 'Kernel::System::CustomerAuth::LDAP';
  $Self->{'Customer::AuthModule::LDAP::Host'}   = ['ad1.intern.companyx.de'];
  $Self->{'Customer::AuthModule::LDAP::BaseDN'} = 'DC=intern,DC=CompanyX,DC=de';
  $Self->{'Customer::AuthModule::LDAP::UID'}    = 'sAMAccountName';
  $Self->{'Customer::AuthModule::LDAP::SearchUserDN'} = 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
  $Self->{'Customer::AuthModule::LDAP::SearchUserPw'} = 'xxxxxxxxxx';
  $Self->{'Customer::AuthModule::LDAP::AlwaysFilter'} = '(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';
  #$Self->{'Customer::AuthModule::LDAP::UserSuffix'} = '@domain.com';
  #$Self->{'Customer::AuthModule::LDAP::UserLowerCase'} = 0;
  #$Self->{'Customer::AuthModule::LDAP::Charset'} = 'iso-8859-1';
  $Self->{'Customer::AuthModule::LDAP::Params'} = {
      port    => 389,
      timeout => 120,
      async   => 0,
      version => 3,
  };


Im letzten Beispiel wurden nur Nutzereinträge verwendet bei denen das Attribut "departmentNumber" gesetzt ist. Sollte das AD nur unvollständig gepflegt sein, fehlen dadurch einige Einträge. Für diese wird nachfolgend ein sekundäres Kundendatenbackend definiert, in welchem die Mailadresse als Kundennummer verwendet wird.


  $Self->{'CustomerUser1'} = {
      Name   => 'LDAP Backend',
      Module => 'Kernel::System::CustomerUser::LDAP',
      Params => {
          Host   => ['ad1.intern.companyx.de'],
          BaseDN => 'DC=intern,DC=CompanyX,DC=de',
          SSCOPE => 'sub',
          UserDN => 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de',
          UserPw => 'xxxxxxxxxx',
          AlwaysFilter =>  '(&(objectClass=user)(!(departmentNumber=*))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))',
          SourceCharset => 'utf-8',
          DestCharset   => 'utf-8',
          Die           => 0,
          Params        => {
              port    => 389,
              timeout => 120,
              async   => 0,
              version => 3,
          },
      },
      CustomerKey                        => 'sAMAccountName',
      CustomerID                         => 'sAMAccountName',
      CustomerUserListFields             => [ 'sn', 'givenname', 'sAMAccountName', 'mail' ],
      CustomerUserSearchFields           => [ 'sAMAccountName', 'sn', 'givenname', 'mail' ],
      CustomerUserSearchPrefix           => '*',
      CustomerUserSearchSuffix           => '*',
      CustomerUserSearchListLimit        => 250,
      CustomerUserPostMasterSearchFields => ['mail'],
      CustomerUserNameFields => [ 'givenname', 'sn' ],
      CustomerUserExcludePrimaryCustomerID => 0,

      #CustomerUserValidFilter => '(!(description=gesperrt))',
      #AdminSetPreferences => 0,
      #CustomerCompanySupportPersonalCustomerID => 0,


      CacheTTL => 3600,
      Map      => [
          # note: Login, Email and CustomerID needed!
          # var, frontend, storage, shown (1=always,2=lite), required, storage-type, http-link, readonly
          [ 'UserPosition',    'Position',     'title',                      1, 0, 'var', '', 0 ],
          [ 'UserSalutation',  'Salutation',   'physicalDeliveryOfficeName', 1, 0, 'var', '', 0 ],
          [ 'UserTitle',       'Title',        'employeeType',               1, 0, 'var', '', 0 ],
          [ 'UserFirstname',   'Firstname',    'givenname',                  1, 1, 'var', '', 0 ],
          [ 'UserLastname',    'Lastname',     'sn',                         1, 1, 'var', '', 0 ],
          [ 'UserLogin',       'Username',     'sAMAccountName',             1, 1, 'var', '', 0 ],
          [ 'UserEmail',       'Email',        'mail',                       1, 1, 'var', '', 0 ],
          [ 'UserCustomerID',  'CustomerID',   'sAMAccountName',             1, 1, 'var', '', 0 ],
          [ 'UserDepartment1', 'Department 1', 'division',                   1, 0, 'var', '', 0 ],
          [ 'UserDepartment2', 'Department 2', 'department',                 1, 0, 'var', '', 0 ],
          [ 'UserCompany',     'Company',      'company',                    1, 0, 'var', '', 0 ],
          [ 'UserPhone',       'Phone',        'telephonenumber',            1, 0, 'var', '', 0 ],
          [ 'UserAddress',     'Address',      'postaladdress',              1, 0, 'var', '', 0 ],
          [ 'UserRoom',        'Room',         'roomNumber',                 1, 0, 'var', '', 0 ],
          [ 'UserEmployeeID',  'Personalnr.',  'employeeID',                 1, 0, 'var', '', 0 ],
          [ 'UserComment',     'Comment',      'description',                1, 0, 'var', '', 0 ],
      ],
  };

  $Self->{'Customer::AuthModule1'}             = 'Kernel::System::CustomerAuth::LDAP';
  $Self->{'Customer::AuthModule::LDAP::Host1'} = ['ad1.intern.companyx.de'];
  $Self->{'Customer::AuthModule::LDAP::BaseDN1'} = 'DC=intern,DC=CompanyX,DC=de';
  $Self->{'Customer::AuthModule::LDAP::UID1'} = 'sAMAccountName';
  $Self->{'Customer::AuthModule::LDAP::SearchUserDN1'} = 'CN=Ldap-User,OU=Systemkonten,DC=intern,DC=CompanyX,DC=de';
  $Self->{'Customer::AuthModule::LDAP::SearchUserPw1'} = 'xxxxxxxxxx';
  $Self->{'Customer::AuthModule::LDAP::AlwaysFilter1'} = '(&(objectClass=user)(!(departmentNumber=*))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))';

  #$Self->{'Customer::AuthModule::LDAP::UserSuffix1'} = '@domain.com';
  #$Self->{'Customer::AuthModule::LDAP::UserLowerCase1'} = 0;
  #$Self->{'Customer::AuthModule::LDAP::Charset1'} = 'iso-8859-1';
  $Self->{'Customer::AuthModule::LDAP::Params1'} = {
      port    => 389,
      timeout => 120,
      async   => 0,
      version => 3,
  };



...talkin' 'bout KIX.

Seb

Kann eine Anmeldung mit dem AD-Account dann auch durch die KIX-Rest-API verwendet werden?
Gruß Seb