Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP: Add FreeIPA Implementation #2177

Closed
9 tasks done
james-d-elliott opened this issue Jul 13, 2021 · 17 comments · Fixed by #4482
Closed
9 tasks done

LDAP: Add FreeIPA Implementation #2177

james-d-elliott opened this issue Jul 13, 2021 · 17 comments · Fixed by #4482
Labels
area/ldap LDAP related features/bugs status/ready Is ready to try/merge type/feature Request for adding a new feature

Comments

@james-d-elliott
Copy link
Member

james-d-elliott commented Jul 13, 2021

Feature Request

Description

Add an implementation for FreeIPA with sane defaults. Criteria is as follows:

Users filter should exclude:

  • Users which are disabled if this feature exists in FreeIPA.
  • Users which have expired passwords if this feature exists in FreeIPA.

Values Needed:

  • distinguished_name_attribute (new attribute)
  • users_filter (see above, needs particular attention)
  • username_attribute
  • mail_attribute
  • display_name_attribute
  • groups_attribute
  • group_name_attribute

Use Case

Easier LDAP Implementation.

@deathbybandaid
Copy link

I normally am opposed to comments that don't contribute to a discussion, but my purpose right now is to be a voice of a humble home-labber that is very interested in the development of this feature.

I'd like to be able to create a group in freeipa called sonarr_users for users of sonarr versus specifying individuals.

Doing so makes authelia more fluid, as it doesn't require a config-change+restart to implement, as ldap queries are done live.

@james-d-elliott
Copy link
Member Author

I'm happy to put some time into this. I've just not had someone who actively uses it and is actually constructive with their feedback.

Could you explain what you mean by restarting? Authelia already periodically queries LDAP for up-to-date information.

@deathbybandaid
Copy link

As of now, authelia isn't pulling group memberships from FreeIPA properly.

Example, I am using authelia to protect sonarr.

    - domain:
      - 'sonarr.my.domain'
      subject:
      - 'user:user_a'
      - 'user:user_b'
      policy: one_factor

If I want to modify what users can access sonarr, I have to modify the yaml and restart authelia.

The prefered method would be to

    - domain:
      - 'sonarr.my.domain'
      subject:
      - 'group:sonarr_users'
      policy: one_factor

This way, I can modify a group membership in freeipa, without having to restart authelia for the user permissions to take effect.

@james-d-elliott
Copy link
Member Author

Yeah gotcha. So it's not exactly restart related it's just that it doesn't work because FreeIPA doesn't use a RFC compliant group membership method.

That's the main issue I was aiming to tackle with a FreeIPA implementation.

@deathbybandaid
Copy link

It's mostly a convenience thing, really

@james-d-elliott
Copy link
Member Author

Can you share your LDAP section minus password (feel free to anonymize the DN's), as well as your compose for FreeIPA itself?

@deathbybandaid
Copy link

deathbybandaid commented Dec 5, 2022

Here's my ldap section in my authelia configuration.yml

authentication_backend:
  password_reset:
    disable: true
    custom_url: ""
  refresh_interval: 5m
  ldap:
    implementation: custom
    url: ldaps://freeipa1.mylocal.domain
    base_dn: dc=mylocal,dc=domain
    username_attribute: uid
    users_filter: (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))
    additional_groups_dn: cn=groups,cn=accounts
    groups_filter: (&(member=uid={input},cn=accounts,dc=mylocal,dc=domain)(objectClass=groupofnames))
    group_name_attribute: cn
    mail_attribute: mail
    display_name_attribute: displayName
    user: uid=svc_authelia,cn=users,cn=accounts,dc=mylocal,dc=domain
    password: totally_the_most_secure_password

Not sure what you mean by my freeipa compose

Edit: if you mean docker-compose, I don't use docker for either authelia or freeipa

@james-d-elliott
Copy link
Member Author

Turns out the issue is FreeIPA requires the Krb GSSAPI SASL authentication to retrieve membership information of users which is the actual cause. The library we use currently doesn't support this unfortunately so the only way for now would be if there is a way to disable this feature either entirely or for a particular service user.

@james-d-elliott
Copy link
Member Author

This config should actually work now I've managed to dig through their implementation more (didn't manage to test it as FreeIPA's official docker container is absolute garbage):

authentication_backend:
  disable_reset_password: false
  refresh_interval: 5m
  ldap:
    implementation: custom
    url: ldaps://freeipa.example.com
    base_dn: DC=example,DC=com
    additional_users_dn: CN=users,CN=accounts
    users_filter: '(&({username_attribute}={input})(objectClass=person))'
    username_attribute: uid
    mail_attribute: mail
    display_name_attribute: displayName
    additional_groups_dn: ''
    groups_filter: '(&(member={dn})(objectClass=groupOfNames))'
    group_name_attribute: cn
    user: UID=admin,CN=users,CN=accounts,DC=example,DC=com

@james-d-elliott
Copy link
Member Author

james-d-elliott commented Dec 5, 2022

Okay I settled on this setting suite for now, works perfectly with groups (see logs), and prevents disabled accounts from logging in (tested on FreeIPA 4.10 on AlmaLinux 9):

authentication_backend:
  disable_reset_password: false
  refresh_interval: 5m
  ldap:
    implementation: custom
    url: ldaps://freeipa.example.com
    tls:
      server_name: freeipa.example.com
      skip_verify: true
    base_dn: DC=ipa,DC=example,DC=com
    additional_users_dn: CN=users,CN=accounts
    users_filter: '(&({username_attribute}={input})(objectClass=person)(!(nsAccountLock=TRUE)))'
    username_attribute: uid
    mail_attribute: mail
    display_name_attribute: displayName
    additional_groups_dn: ''
    groups_filter: '(&(member={dn})(objectClass=groupOfNames))'
    group_name_attribute: cn
    user: UID=authelia,CN=users,CN=accounts,DC=ipa,DC=example,DC=com
    password: authelia
time="2022-12-05T12:16:10Z" level=trace msg="Detected user filter is (&(uid=james)(objectClass=person)(!(nsAccountLock=TRUE)))"
time="2022-12-05T12:16:10Z" level=trace msg="Performing user search" attr="[uid mail displayName]" base_dn="CN=users,CN=accounts,DC=ipa,DC=example,DC=com" deref=0 filter="(&(uid=james)(objectClass=person)(!(nsAccountLock=TRUE)))" scope=2
time="2022-12-05T12:16:10Z" level=debug msg="Mark 1FA authentication attempt made by user 'james'" method=POST path=/api/firstfactor remote_ip=4.2.2.2time="2022-12-05T12:16:10Z" level=debug msg="Successful 1FA authentication attempt made by user 'james'" method=POST path=/api/firstfactor remote_ip=4.2.2.2
time="2022-12-05T12:16:10Z" level=trace msg="Detected user filter is (&(uid=james)(objectClass=person)(!(nsAccountLock=TRUE)))"
time="2022-12-05T12:16:10Z" level=trace msg="Performing user search" attr="[uid mail displayName]" base_dn="CN=users,CN=accounts,DC=ipa,DC=example,DC=com" deref=0 filter="(&(uid=james)(objectClass=person)(!(nsAccountLock=TRUE)))" scope=2
time="2022-12-05T12:16:10Z" level=trace msg="Computed groups filter is (&(member=uid=james,cn=users,cn=accounts,dc=ipa,dc=example,dc=com)(objectClass=groupOfNames))"
time="2022-12-05T12:16:10Z" level=trace msg="Performing group search" attr="[cn]" base_dn="DC=ipa,DC=example,DC=com" deref=0 filter="(&(member=uid=james,cn=users,cn=accounts,dc=ipa,dc=example,dc=com)(objectClass=groupOfNames))" scope=2
time="2022-12-05T12:16:10Z" level=trace msg="Profile details for user 'james' => groups: [ipausers], emails [james@ipa.example.com]" method=POST path=/api/firstfactor remote_ip=4.2.2.2

@deathbybandaid
Copy link

Is that with current code, or unreleased code?

@james-d-elliott
Copy link
Member Author

Current.

@deathbybandaid
Copy link

I'll give it a try shortly

@james-d-elliott
Copy link
Member Author

Log message after adding two groups to the user, logging out of authelia, ensuring authelia DOES NOT restart, and logging in again:

time="2022-12-05T12:34:52Z" level=trace msg="Profile details for user 'james' => groups: [admins ipausers trust admins], emails [james@ipa.example.com]" method=POST path=/api/firstfactor remote_ip=4.2.2.2

@deathbybandaid
Copy link

Can confirm, this worked wonderfully for me, and my sonarr_users group works great

Freeipa 4.9.6 on Rocky Linux 8.5

I am running updates on my freeipa servers and will edit when done

When updates are done it should be Freeipa 4.9.10 on Rocky Linux 8.7
(had to restore a backup, as the upgrade fails if freeipa doesn't have the admin user enabled)

@deathbybandaid
Copy link

Confirmed working on Freeipa 4.9.10 on Rocky Linux 8.7

@james-d-elliott james-d-elliott added status/ready Is ready to try/merge area/ldap LDAP related features/bugs labels Dec 5, 2022
@james-d-elliott
Copy link
Member Author

PR4482 will close part of this adding the freeipa implementation (configuration defaults only, unlike activedirectory which is technically special), and PR4483 adds time replacements which allows limiting users to those who don't have expired accounts/passwords (this will be the default with the freeipa users filter).

james-d-elliott added a commit that referenced this issue Dec 21, 2022

This adds a FreeIPA LDAP implementation which purely adds sane defaults for FreeIPA. There are no functional differences just when the implementation option is set to 'freeipa' sane defaults which should be sufficient for most use cases are set. See the documentation at https://www.authelia.com/r/ldap#defaults for more details.

Closes #2177, Closes #2161
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/ldap LDAP related features/bugs status/ready Is ready to try/merge type/feature Request for adding a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants