hermes-client plugins

The client plugins are grouped by categories serving the same goal over several target types. There is currently only one plugin category:

  • usersgroups: manage users, groups, userpasswords and groups membership

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Subsections of hermes-client plugins

usergroups

Manage users, groups, userpasswords and groups membership.

Available clients are:

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Subsections of usergroups

adpypsrp

Description

This client will handle Users, Groups and UserPasswords events, and store data into an Active Directory through Powershell commands across pypsrp.

The settings list standardAttributes contains available cmdlet parameters used for Users (New-ADUser / Set-ADUser) and Groups (New-ADGroup / Set-ADGroup). The settings list otherAttributes may contains available LDAP display name (ldapDisplayName) attributes to manage those that are not represented by cmdlet parameters for Users and Groups.

The local Datamodel keys MUST exist in standardAttributes or otherAttributes, and will be used as cmdlet parameters with associated values, allowing to handle every AD attributes.

The GroupsMembers will only associate a User with a Group. The SubGroupsMembers will only associate a Group with a Group, allowing to handle nested groups.

To avoid security issues and corner cases with trashbin, a complex random password is set when user is created. This unknown password will be overwritten by the next UserPassword event of the User. This avoids having an enabled account with no password.

The trashbin will only disable the account.

Configuration

hermes-client-usersgroups_adpypsrp:
  WinRM:  # For options details, you may look at https://pypi.org/project/pypsrp/ - "Connection"
    # MANDATORY: AD server URI and port
    host: radon1.in.insa-strasbourg.fr
    port: 5986
    # MANDATORY: AD server credentials
    login: administrator
    password: "s3cReT_p4s5w0rD"
    # Default: true
    ssl: true
    # Default: true
    ssl_cert_validation: false
    # Default: true
    credssp_disable_tlsv1_2: true
    # Default: "auto". Valid values are [auto, always, never]
    encryption: always
    # Default: "wsman"
    path: "wsman"
    # Default: "negotiate". Valid values are [basic, certificate, negotiate, ntlm, kerberos, credssp]
    auth: kerberos
    # Default: "WSMAN". Override the service part of the calculated SPN used when authenticating the server.
    # This is only valid if negotiate auth negotiated Kerberos or kerberos was explicitly set.
    # If you obtain an error "Server not found in Kerberos database", you may try to set HTTP here.
    negotiate_service: WSMAN

  AD_domain:
    # MANDATORY: AD domain name and DN
    name: in.insa-strasbourg.fr
    dn: DC=in,DC=insa-strasbourg,DC=fr
    # MANDATORY: OUs where Users and Groups will be stored
    users_ou: OU=INSA,OU=People,DC=in,DC=insa-strasbourg,DC=fr
    groups_ou: OU=INSA,OU=Groups,DC=in,DC=insa-strasbourg,DC=fr

  # Optional, allows to force each user to be added to the specified group list.
  # Group membership is only added when the user is created: any change to this parameter's value
  # will only impact users created subsequently
  Users_mandatory_groups:
    - MandatoryGroup1
    - MandatoryGroup2

  # Defines cmdlet parameters that can be set, and the valid type of the associated value
  # You really should set it as is.
  standardAttributes:
    Users:
      AccountExpirationDate: "<DateTime>"
      AccountNotDelegated: "<Boolean>"
      AllowReversiblePasswordEncryption: "<Boolean>"
      AuthenticationPolicy: "<ADAuthenticationPolicy>"
      AuthenticationPolicySilo: "<ADAuthenticationPolicySilo>"
      AuthType: "<ADAuthType>"
      CannotChangePassword: "<Boolean>"
      ChangePasswordAtLogon: "<Boolean>"
      City: "<String>"
      Company: "<String>"
      CompoundIdentitySupported: "<Boolean>"
      Country: "<String>"
      # Credential: "<PSCredential>" # Useless: Specifies the user account credentials to use to perform this task
      Department: "<String>"
      Description: "<String>"
      DisplayName: "<String>"
      Division: "<String>"
      EmailAddress: "<String>"
      EmployeeID: "<String>"
      EmployeeNumber: "<String>"
      Enabled: "<Boolean>"
      Fax: "<String>"
      GivenName: "<String>"
      HomeDirectory: "<String>"
      HomeDrive: "<String>"
      HomePage: "<String>"
      HomePhone: "<String>"
      KerberosEncryptionType: "<ADKerberosEncryptionType>"
      LogonWorkstations: "<String>"
      Manager: "<ADUser>"
      MobilePhone: "<String>"
      Office: "<String>"
      OfficePhone: "<String>"
      Organization: "<String>"
      OtherName: "<String>"
      PasswordNeverExpires: "<Boolean>"
      PasswordNotRequired: "<Boolean>"
      POBox: "<String>"
      PostalCode: "<String>"
      # PrincipalsAllowedToDelegateToAccount: "<ADPrincipal[]>" # Won't be set
      ProfilePath: "<String>"
      SamAccountName: "<String>"
      ScriptPath: "<String>"
      # Server: "<String>" # Useless: Specifies the Active Directory Domain Services instance to connect to
      SmartcardLogonRequired: "<Boolean>"
      State: "<String>"
      StreetAddress: "<String>"
      Surname: "<String>"
      Title: "<String>"
      # TrustedForDelegation: "<Boolean>" # Won't be set
      UserPrincipalName: "<String>"

    Groups:
      AuthType: "<ADAuthType>"
      # Credential: "<PSCredential>" # Useless: Specifies the user account credentials to use to perform this task
      Description: "<String>"
      DisplayName: "<String>"
      GroupCategory: "<ADGroupCategory>"
      GroupScope: "<ADGroupScope>"
      HomePage: "<String>"
      ManagedBy: "<ADPrincipal>"
      SamAccountName: "<String>"
      # Server: "<String>" # Useless: Specifies the Active Directory Domain Services instance to connect to

  # Defines LDAP display name (ldapDisplayName) to handle, that are not handled with standardAttributes.
  # You can set your desired values. The values below are just here for example.
  otherAttributes:
    Users:
      otherMobile: "<String[]>"
      otherTelephone: "<String[]>"
      url: "<String[]>"

  # Optional random password generation settings. Default: values specified below
  # Random password is generated to initialize a user whose password is not yet available,
  # or when the user password is removed but the user still exists
  random_passwords:
    # Password length
    length: 32
    # If true, the generated password may contains some upper case letters
    with_upper_letters: true
    # The generated password will contain at least this number of upper case letters
    minimum_number_of_upper_letters: 1
    # If true, the generated password may contains some lower case letters
    with_lower_letters: true
    # The generated password will contain at least this number of lower case letters
    minimum_number_of_lower_letters: 1
    # If true, the generated password may contains some numbers
    with_numbers: true
    # The generated password will contain at least this number of numbers
    minimum_number_of_numbers: 1
    # If true, the generated password may contains some special chars
    with_special_chars: true
    # The generated password will contain at least this number of special chars
    minimum_number_of_special_chars: 1
    # If true, the generated password won't contains the chars specified in 'ambigous_chars_dictionary'
    avoid_ambigous_chars: false
    # The dictionary of ambigous chars (case sensitive) that may be forbidden in password, even if some are present in other dictionnaries
    ambigous_chars_dictionary: "lIO01"
    # The dictionary of letters (case unsensitive) allowed in password
    letters_dictionary: "abcdefghijklmnopqrstuvwxyz"
    # The dictionary of special chars allowed in password
    special_chars_dictionary: "!@#$%^&*"

Datamodel

The following data types may be set up:

  • Users: requires the attribute SamAccountName to be set
  • UserPasswords: obviously requires Users, and requires the attribute user_pkey corresponding to the primary keys of Users, and the attribute password. All other attributes will be ignored
  • Groups: requires the attribute SamAccountName to be set
  • GroupsMembers: obviously requires Users and Groups, and requires the attributes user_pkey and group_pkey corresponding to the primary keys of Users and Groups. All other attributes will be ignored
  • SubGroupsMembers: obviously requires Groups, and requires that the subgroup_pkey and group_pkey attributes match the primary key of the subgroup to be assigned, and that of the assignment group, respectively. All other attributes will be ignored
  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        user_pkey: user_primary_key_on_server
        SamAccountName: login_on_server
        UserPrincipalName: "{{ login_on_server ~ '@YOU.AD.DOMAIN.TLD' }}"
        # Not mandatory, only for example:
        MobilePhone: "{{ (mobile | default([None]))[0] }}" # <String>
        otherMobile: "{{ (mobile | default([]))[1:]  }}" # <String[]>
        # ...

    UserPasswords:
      hermesType: your_server_UserPasswords_type_name
      attrsmapping:
        user_pkey: user_primary_key_on_server
        password: cleartext_password_on_server
        # ...

    Groups:
      hermesType: your_server_Groups_type_name
      attrsmapping:
        group_pkey: group_primary_key_on_server
        SamAccountName: group_name_on_server
        # ...

    GroupsMembers:
      hermesType: your_server_GroupsMembers_type_name
      attrsmapping:
        user_pkey: user_primary_key_on_server
        group_pkey: group_primary_key_on_server
        # ...

    SubGroupsMembers:
      hermesType: your_server_SubGroupsMembers_type_name
      attrsmapping:
        subgroup_pkey: subgroup_primary_key_on_server
        group_pkey: group_primary_key_on_server
        # ...

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

bsspartage

Description

This client will handle Users, UserPasswords, Groups, GroupsMembers, GroupsSenders and Ressources events, and store data into the PARTAGE dashboard through its API, handled by libPythonBssApi.

To avoid security issues, if no hash is available at user creation, a complex random password will be set. This unknown password will be changed when a userPassword attribute will be set to the User or to the UserPassword. This avoids having an enabled account with no password.

The trashbin will only disable the account.

Configuration

You have to configure an authentication mapping containing all domains managed by this client as keys, and their API key as values.

hermes-client-usersgroups_bsspartage:
  authentication:
    example.com: "Secret_API_key_of_example.com"
    subdomain.example.com: "Secret_API_key_of_subdomain.example.com"
  
  # When an attribute has no more value, the default behavior is to keep its latest value in place.
  # This setting allow to override this behaviour for the specified attributes, with the replacement values.
  # Please note that it is forbidden to set Users.userPassword, as the default behavior is to generate a new random password.
  # It is also forbidden to set null values, as this reverts to the default behavior. In this case, simply remove the affected attribute from this list.
  #
  # The values set below are the default values used if default_removed_values is not set
  default_removed_values:
    Users:
      co: ""
      company: ""
      description: ""
      displayName: ""
      facsimileTelephoneNumber: ""
      givenName: ""
      homePhone: ""
      initials: ""
      l: ""
      mobile: ""
      name: ""
      pager: ""
      postalCode: ""
      st: ""
      street: ""
      telephoneNumber: ""
      title: ""
      zimbraNotes: ""
      zimbraPrefMailForwardingAddress: ""
      zimbraMailCanonicalAddress: ""
      zimbraPrefFromDisplay: ""
      zimbraMailQuota: 0
    Groups:
      # Values should be set to empty strings, but a bug in API is ignoring them.
      # This bug has been notified to PARTAGE's team.
      description: "-" 
      displayName: "-"
      zimbraNotes: "-"
    Resources:
      co: ""
      description: ""
      l: ""
      postalCode: ""
      st: ""
      street: ""
      zimbraCalResBuilding: ""
      zimbraCalResContactEmail: ""
      zimbraCalResContactName: ""
      zimbraCalResContactPhone: ""
      zimbraCalResFloor: ""
      zimbraCalResLocationDisplayName: ""
      zimbraCalResRoom: ""
      zimbraCalResSite: ""
      zimbraNotes: ""
      zimbraCalResCapacity: "-1"

  # Optional random password generation settings. Default: values specified below
  # Random password is generated to initialize a user whose password is not yet available
  random_passwords:
    # Password length
    length: 32
    # If true, the generated password may contains some upper case letters
    with_upper_letters: true
    # The generated password will contain at least this number of upper case letters
    minimum_number_of_upper_letters: 1
    # If true, the generated password may contains some lower case letters
    with_lower_letters: true
    # The generated password will contain at least this number of lower case letters
    minimum_number_of_lower_letters: 1
    # If true, the generated password may contains some numbers
    with_numbers: true
    # The generated password will contain at least this number of numbers
    minimum_number_of_numbers: 1
    # If true, the generated password may contains some special chars
    with_special_chars: true
    # The generated password will contain at least this number of special chars
    minimum_number_of_special_chars: 1
    # If true, the generated password won't contains the chars specified in 'ambigous_chars_dictionary'
    avoid_ambigous_chars: false
    # The dictionary of ambigous chars (case sensitive) that may be forbidden in password, even if some are present in other dictionnaries
    ambigous_chars_dictionary: "lIO01"
    # The dictionary of letters (case unsensitive) allowed in password
    letters_dictionary: "abcdefghijklmnopqrstuvwxyz"
    # The dictionary of special chars allowed in password
    special_chars_dictionary: "!@#$%^&*"

Datamodel

The following data types may be set up:

  • Users: for users accounts. Requires the attribute name and sn to be set, a facultative aliases attribute may bet set, and the others are attributes as defined and used by libPythonBssApi and are facultative. Note that zimbraAllowFromAddress, zimbraFeatureContactsEnabled and zimbraMailForwardingAddress attributes are not supported by libPythonBssApi.
  • UserPasswords: obviously require Users, and requires that its primary keys are corresponding to the primary keys of Users, and requires the attribute userPassword that have to contain a valid LDAP hash. All other attributes will be ignored. As the userPassword attribute can also be managed by Users, you have to choose: either you manage it by Users, or by UserPasswords, but in no case should you use both at the same time for obvious reasons.
  • Groups: for groups and distribution lists. Requires the attribute name and zimbraMailStatus to be set, a facultative aliases attribute may bet set, and the others are attributes as defined and used by libPythonBssApi and are facultative.
  • GroupsMembers: to add users as group members. Obviously require Users and Groups, and requires the attributes user_pkey and group_pkey corresponding to the primary keys of Users and Groups. All other attributes will be ignored.
  • GroupsSenders: to add users as group senders. Obviously require Users and Groups, and requires the attributes user_pkey and group_pkey corresponding to the primary keys of Users and Groups. All other attributes will be ignored.
  • Resources: for resources. Requires the attribute name, zimbraCalResType and displayName to be set, and the others are attributes as defined and used by libPythonBssApi and are facultative.
Warning

If you’re setting the Users.zimbraCOSId, you should avoid setting COS-managed attributes in your datamodel, as overriding the COS default value may lead to unexpected behaviours.

Warning

Since the API does not allow renaming Groups and Resources, this operation is done by deleting the old instance and recreating the new one in the process. However, this can cause loss of links and information (e.g. resource calendars), and it is probably best to avoid these renames.

Tip

To handle Users.zimbraCOSId, it is likely that your data source provides a name rather than the COSId. It is possible to declare a mapping table in Jinja directly in your configuration:

  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        # ...
        zimbraCOSId: >-
          {{
              {
                'name_of_cos1': '11111111-1111-1111-1111-111111111111',
                'name_of_cos2': '22222222-2222-2222-2222-222222222222',
                'name_of_cos3': '33333333-3333-3333-3333-333333333333',
              }[zimbraCOSName_value_from_server | default('name_of_cos1') | lower]
              | default('11111111-1111-1111-1111-111111111111')
          }}          
        # ...
  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        # User primary email address <Valid email address>
        name: name_value_from_server
        # User last name <String>
        sn: sn_value_from_server

        # List of aliases for this user <String[]>
        aliases: aliases_value_from_server
        # User EPPN number <String>
        carLicense: carLicense_value_from_server
        # Country name <String>
        co: co_value_from_server
        # Company or institution name <String>
        company: company_value_from_server
        # Account description <String>
        description: description_value_from_server
        # Name displayed in emails <String>
        displayName: displayName_value_from_server
        # User fax <String>
        facsimileTelephoneNumber: facsimileTelephoneNumber_value_from_server
        # User first name <String>
        givenName: givenName_value_from_server
        # User home phone <String>
        homePhone: homePhone_value_from_server
        # Initial (Mr. or Mrs.) <String>
        initials: initials_value_from_server
        # User city <String>
        l: l_value_from_server
        # User mobile number <String>
        mobile: mobile_value_from_server
        # User shortcut number <String>
        pager: pager_value_from_server
        # Postal code <String>
        postalCode: postalCode_value_from_server
        # User state <String>
        st: st_value_from_server
        # User street <String>
        street: street_value_from_server
        # User phone <String>
        telephoneNumber: telephoneNumber_value_from_server
        # User title <String>
        title: title_value_from_server
        # Password hash <String>
        userPassword: userPassword_value_from_server
        # Account status (default active) <String(active, closed, locked)>
        zimbraAccountStatus: zimbraAccountStatus_value_from_server
        # Class of service Id <String>
        zimbraCOSId: zimbraCOSId_value_from_server
        # Briefcase tab <String (TRUE, FALSE)>
        zimbraFeatureBriefcasesEnabled: zimbraFeatureBriefcasesEnabled_value_from_server
        # Calendar tab <String (TRUE, FALSE)>
        zimbraFeatureCalendarEnabled: zimbraFeatureCalendarEnabled_value_from_server
        # Mail tab <String (TRUE, FALSE)>
        zimbraFeatureMailEnabled: zimbraFeatureMailEnabled_value_from_server
        # Allow user to specify forward address <String (TRUE, FALSE)>
        zimbraFeatureMailForwardingEnabled: zimbraFeatureMailForwardingEnabled_value_from_server
        # Options tab <String (TRUE, FALSE)>
        zimbraFeatureOptionsEnabled: zimbraFeatureOptionsEnabled_value_from_server
        # Tasks tab <String (TRUE, FALSE)>
        zimbraFeatureTasksEnabled: zimbraFeatureTasksEnabled_value_from_server
        # Hide in GAL <String (TRUE, FALSE)>
        zimbraHideInGal: zimbraHideInGal_value_from_server
        # 0=unlimited <Integer (bytes)>
        zimbraMailQuota: zimbraMailQuota_value_from_server
        # Free notes <String>
        zimbraNotes: zimbraNotes_value_from_server
        # Must change password at next login <String (TRUE, FALSE)>
        zimbraPasswordMustChange: zimbraPasswordMustChange_value_from_server
        # Forward address entered by user <Valid email address>
        zimbraPrefMailForwardingAddress: zimbraPrefMailForwardingAddress_value_from_server
        # Do not keep a copy of mails on the local client <String (TRUE, FALSE)>
        zimbraPrefMailLocalDeliveryDisabled: zimbraPrefMailLocalDeliveryDisabled_value_from_server
        # Email address visible for outgoing messages <String>
        zimbraMailCanonicalAddress: zimbraMailCanonicalAddress_value_from_server
        # Display name visible for outgoing messages <String>
        zimbraPrefFromDisplay: zimbraPrefFromDisplay_value_from_server

    UserPasswords:
      hermesType: your_server_UserPasswords_type_name
      attrsmapping:
        # Password hash <String>
        userPassword: userPassword_value_from_server

    Groups:
      hermesType: your_server_Groups_type_name
      attrsmapping:
        # Group primary email address <Valid email address>
        name: name_value_from_server
        # Discriminant distribution list/group <String (enabled, disabled)>
        zimbraMailStatus: zimbraMailStatus_value_from_server
        
        # List of aliases for this group <String[]>
        aliases: aliases_value_from_server
        # Group description <String>
        description: description_value_from_server
        # Display name <String>
        displayName: displayName_value_from_server
        # Report available shares to new members <String (TRUE, FALSE)>
        zimbraDistributionListSendShareMessageToNewMembers: zimbraDistributionListSendShareMessageToNewMembers_value_from_server
        # Hide group in GAL <String (TRUE, FALSE)>
        zimbraHideInGal: zimbraHideInGal_value_from_server
        # Free notes <String>
        zimbraNotes: zimbraNotes_value_from_server

    GroupsMembers:
      hermesType: your_server_GroupsMembers_type_name
      attrsmapping:
        user_pkey: user_pkey_value_from_server
        group_pkey: group_pkey_value_from_server

    GroupsSenders:
      hermesType: your_server_GroupsSenders_type_name
      attrsmapping:
        user_pkey: user_pkey_value_from_server
        group_pkey: group_pkey_value_from_server
    
    Resources:
      hermesType: your_server_Resources_type_name
      attrsmapping:
        # Resource primary email address <Valid email address>
        name: name_value_from_server
        # Display name <String>
        displayName: displayName_value_from_server
        # Resource type <String (Location, Equipment)>
        zimbraCalResType: zimbraCalResType_value_from_server
        
        # Country name <String>
        co: co_value_from_server
        # Description <String>
        description: description_value_from_server
        # Resource city <String>
        l: l_value_from_server
        # Postal code <String>
        postalCode: postalCode_value_from_server
        # Resource state <String>
        st: st_value_from_server
        # Resource street <String>
        street: street_value_from_server
        # Password hash <String>
        userPassword: userPassword_value_from_server
        # Resource status (default active) <String (active, closed)>
        zimbraAccountStatus: zimbraAccountStatus_value_from_server
        # Automatically accept or decline invitations <String (TRUE, FALSE)>
        zimbraCalResAutoAcceptDecline: zimbraCalResAutoAcceptDecline_value_from_server
        # Automatically decline invitations if there is a risk of conflict <String (TRUE, FALSE)>
        zimbraCalResAutoDeclineIfBusy: zimbraCalResAutoDeclineIfBusy_value_from_server
        # Automatically decline recurring invitations <String (TRUE, FALSE)>
        zimbraCalResAutoDeclineRecurring: zimbraCalResAutoDeclineRecurring_value_from_server
        # Building <String>
        zimbraCalResBuilding: zimbraCalResBuilding_value_from_server
        # Capacity <Integer>
        zimbraCalResCapacity: zimbraCalResCapacity_value_from_server
        # Contact email address <String>
        zimbraCalResContactEmail: zimbraCalResContactEmail_value_from_server
        # Contact name <String>
        zimbraCalResContactName: zimbraCalResContactName_value_from_server
        # Contact phone <String>
        zimbraCalResContactPhone: zimbraCalResContactPhone_value_from_server
        # Floor <String>
        zimbraCalResFloor: zimbraCalResFloor_value_from_server
        # Name of the displayed location <String>
        zimbraCalResLocationDisplayName: zimbraCalResLocationDisplayName_value_from_server
        # Room <String>
        zimbraCalResRoom: zimbraCalResRoom_value_from_server
        # Site <String>
        zimbraCalResSite: zimbraCalResSite_value_from_server
        # Free notes <String>
        zimbraNotes: zimbraNotes_value_from_server
        # Forward calendar invitations to this address <Array>
        zimbraPrefCalendarForwardInvitesTo: zimbraPrefCalendarForwardInvitesTo_value_from_server

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

flatfiles_emails_of_groups

Description

This client will generate a flat txt file by Groups, containing the e-mail addresses of its members (one by line).

Configuration

hermes-client-usersgroups_flatfiles_emails_of_groups:
  # MANDATORY
  destDir: "/path/where/files/are/stored"

  # Facultative: if set, will generate a file only for the specified group names in list
  onlyTheseGroups:
    - group1
    - group2

Datamodel

The following data types must be set up:

  • Users, requires the following attribute names:
    • user_pkey: the user primary key
    • mail: the user email address
  • Groups, requires the following attribute names:
    • group_pkey: the group primary key
    • name: the group name, that will be compared to those in onlyTheseGroups, and used to name the destination file “groupName.txt”
  • GroupsMembers, requires the following attribute names:
    • user_pkey: the user primary key
    • group_pkey: the group primary key
  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        user_pkey: user_pkey_on_server
        mail: mail_on_server

    Groups:
      hermesType: your_server_Groups_type_name
      attrsmapping:
        group_pkey: group_pkey_on_server
        name: group_name_on_server

    GroupsMembers:
      hermesType: your_server_GroupsMembers_type_name
      attrsmapping:
        user_pkey: user_pkey_on_server
        group_pkey: group_pkey_on_server

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

kadmin_heimdal

Description

This client will handle Users and UserPassword, and store data in an Heimdal Kerberos server.

Configuration

hermes-client-usersgroups_kadmin_heimdal:
  # MANDATORY: Principal with required rights to manage users and passwords in kadmin
  kadmin_login: root/admin
  # MANDATORY: Password of principal above
  kadmin_password: "s3cReT_p4s5w0rD"
  # MANDATORY: Name of Kerberos realm
  kadmin_realm: KERBEROS_REALM

  # Service principal name to get ticket for. Default: kadmin/admin
  kinit_spn: kadmin/admin
  # kinit command to use. Default: kinit.heimdal
  kinit_cmd: kinit.heimdal
  # kadmin command to use. Default: kadmin.heimdal
  kadmin_cmd: kadmin.heimdal
  # kdestroy command to use. Default: kdestroy.heimdal
  kdestroy_cmd: kdestroy.heimdal

  # kadmin additional args to use when adding a user. Must be a list of strings. Default:
  #   - "--max-ticket-life=1 day"
  #   - "--max-renewable-life=1 week"
  #   - "--attributes="
  #   - "--expiration-time=never"
  #   - "--policy=default"
  #   - "--pw-expiration-time=never"
  kadmin_user_add_additional_options:
    - "--max-ticket-life=1 day"
    - "--max-renewable-life=1 week"
    - "--attributes="
    - "--expiration-time=never"
    - "--policy=default"
    - "--pw-expiration-time=never"
  
  # Set to true to start with an already filled Kerberos database. Default: false
  dont_fail_on_existing_user: false

  # Optional random password generation settings. Default: values specified below
  # Random password is generated to initialize a user whose password is not yet available,
  # or when the user password is removed but the user still exists
  random_passwords:
    # Password length
    length: 32
    # If true, the generated password may contains some upper case letters
    with_upper_letters: true
    # The generated password will contain at least this number of upper case letters
    minimum_number_of_upper_letters: 1
    # If true, the generated password may contains some lower case letters
    with_lower_letters: true
    # The generated password will contain at least this number of lower case letters
    minimum_number_of_lower_letters: 1
    # If true, the generated password may contains some numbers
    with_numbers: true
    # The generated password will contain at least this number of numbers
    minimum_number_of_numbers: 1
    # If true, the generated password may contains some special chars
    with_special_chars: true
    # The generated password will contain at least this number of special chars
    minimum_number_of_special_chars: 1
    # If true, the generated password won't contains the chars specified in 'ambigous_chars_dictionary'
    avoid_ambigous_chars: false
    # The dictionary of ambigous chars (case sensitive) that may be forbidden in password, even if some are present in other dictionnaries
    ambigous_chars_dictionary: "lIO01"
    # The dictionary of letters (case unsensitive) allowed in password
    letters_dictionary: "abcdefghijklmnopqrstuvwxyz"
    # The dictionary of special chars allowed in password
    special_chars_dictionary: "!@#$%^&*"

Datamodel

The following data types must be set up:

  • Users, requires the following attribute names:
    • login: the user login, that will be used as principal
  • UserPasswords, requires the following attribute names:
    • password: the password of the user

Obviously, the primary keys of Users and UserPasswords must match to be able to link login with password.

  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        login: login_on_server

    UserPasswords:
      hermesType: your_server_UserPasswords_type_name
      attrsmapping:
        password: password_on_server

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

ldap

Description

This client will handle Users, Groups and UserPasswords events, and store data in an LDAP directory.

The local Datamodel keys will be used as LDAP attributes names, without any constraints, and it is possible to specify some Datamodel keys to ignore (typically the primary keys) that won’t be stored in LDAP directory with the attributesToIgnore setting.

The GroupMembers will only store data (typically LDAP member attribute) in LDAP group entries as it is possible to use LDAP overlays (dynlist or the deprecated memberOf) to dynamically generate the corresponding data in user entries. You should consider reading the propagateUserDNChangeOnGroupMember setting documentation.

LDAP password hashes generation

If you need to generate LDAP password hashes, you may consider looking at ldapPasswordHash attribute plugin.

Configuration

hermes-client-usersgroups_ldap:
    # MANDATORY: LDAP server URI
    uri: ldaps://ldap.example.com:636
    # MANDATORY: LDAP server credentials to use
    binddn: cn=account,dc=example,dc=com
    bindpassword: s3cReT_p4s5w0rD
    # MANDATORY: LDAP base DN
    basedn: dc=example,dc=com
    users_ou: ou=users,dc=example,dc=com
    groups_ou: ou=groups,dc=example,dc=com

    ssl: # Facultative
      # Path to PEM file with CA certs
      cafile: /path/to/INTERNAL-CA-chain.crt # Facultative
      # Path to file with PEM encoded cert for client cert authentication, requires keyfile
      certfile: /path/to/client.crt # Facultative
      # Path to file with PEM encoded key for client cert authentication, requires certfile
      keyfile: /path/to/client.pem # Facultative

    # MANDATORY: Name of DN attribute for Users, UserPasswords and Groups
    # You have to set up values for the three, even if you don't use some of the types
    dnAttributes:
      Users: uid
      UserPasswords: uid
      Groups: cn

    # Depending on group and group membership settings in LDAP, you may use another
    # attribute than the default 'member' attribute to store the DN of group member
    # Facultative. Default value: "member"
    groupMemberAttribute: member

    # Depending on group and group membership settings in LDAP, you usually may want
    # to propagate a user DN change on group member attributes. But sometimes, it
    # may be handled by an overlay, e.g. with memberOf overlay and the
    # memberof-refint/olcMemberOfRefint setting to TRUE
    # If set to true, it requires 'groupsObjectclass' to be defined
    # Facultative. Default value: true
    propagateUserDNChangeOnGroupMember: true

    # If you've set 'propagateUserDNChangeOnGroupMember' to true,
    # you MUST indicate your group objectClass that will be used to search
    # your groups entries
    # Mandatory only if 'propagateUserDNChangeOnGroupMember' is true
    groupsObjectclass: groupOfNames

    # It is possible to set a default value for some attributes for Users, UserPasswords and Groups
    # The default value will be set on added and modified events if the local attribute has no value
    defaultValues:
      Groups:
        member: "" # Hack to allow creation of an empty group, because of the "MUST member" in schema

    # The local attributes listed here won't be stored in LDAP for Users, UserPasswords and Groups
    attributesToIgnore:
      Users:
        - user_pkey
      UserPasswords:
        - user_pkey
      Groups:
        - group_pkey

Datamodel

The following data types may be set up:

  • Users
  • UserPasswords: obviously require Users, and requires the following attribute names user_pkey corresponding to the primary keys of Users
  • Groups
  • GroupsMembers: obviously require Users and Groups, and requires the following attribute names user_pkey group_pkey corresponding to the primary keys of Users and Groups
  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        user_pkey:  user_primary_key_on_server
        uid: login_on_server
        # ...

    UserPasswords:
      hermesType: your_server_UserPasswords_type_name
      attrsmapping:
        user_pkey:  user_primary_key_on_server
        userPassword:  ldap_pwd_hash_list_on_server
        # ...

    Groups:
      hermesType: your_server_Groups_type_name
      attrsmapping:
        group_pkey:  group_primary_key_on_server
        cn:  group_name_on_server
        # ...

    GroupsMembers:
      hermesType: your_server_GroupsMembers_type_name
      attrsmapping:
        user_pkey:  user_primary_key_on_server
        group_pkey:  group_primary_key_on_server
        # ...

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

null

Description

This client will handle Users, Groups and UserPasswords events, but does nothing but logging.

Configuration

Nothing to configure for the plugin.

hermes-client-usersgroups_null:

Datamodel

The following data types may be set up, without any specific constraint as nothing will be processed.

  • Users
  • UserPasswords
  • Groups
  • GroupsMembers
  datamodel:
    Users:
      hermesType: your_server_Users_type_name
      attrsmapping:
        attr1_client:  attr1_server
        # ...

    UserPasswords:
      hermesType: your_server_UserPasswords_type_name
      attrsmapping:
        attr1_client:  attr1_server
        # ...

    Groups:
      hermesType: your_server_Groups_type_name
      attrsmapping:
        attr1_client:  attr1_server
        # ...

    GroupsMembers:
      hermesType: your_server_GroupsMembers_type_name
      attrsmapping:
        attr1_client:  attr1_server
        # ...