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

Fixes #24230: Authentication providers and role mapping settings should be exposed #5408

Conversation

clarktsiory
Copy link
Contributor

@clarktsiory clarktsiory commented Feb 21, 2024

https://issues.rudder.io/issues/24230

We need to know providers properties e.g. : Do they override or extend the user roles defined in the users.xml file ? Can they write password in the users file ?

These properties will be used in user-management plugin to handle some providers logic regarding roles and also for the logic of the UI : Normation/rudder-plugins#668

@clarktsiory clarktsiory changed the base branch from branches/rudder/7.3 to backports/7.3.12/24146 February 21, 2024 17:21
@clarktsiory clarktsiory marked this pull request as draft February 21, 2024 17:22
…gs should be exposed

Fixes #24230: Authentication providers and role mapping settings should be exposed
@clarktsiory clarktsiory force-pushed the bug_24230/authentication_providers_and_role_mapping_settings_should_be_exposed branch from af6a824 to 9a18100 Compare February 23, 2024 15:39
… settings should be exposed

Fixes #24230: Authentication providers and role mapping settings should be exposed
@clarktsiory
Copy link
Contributor Author

PR updated with a new commit

Comment on lines 627 to 634
def update(updated: Vector[UserInfo]): ConnectionIO[Int] = {
// never update the managedBy of an existing user which may have been provided by another origin
val sql =
"""insert into users (id, creationdate, status, managedby, name, email, lastlogin, statushistory, otherinfo)
values (?,?,?,?,? , ?,?,?,?)
on conflict (id) do update
set (creationdate, status, managedby, name, email, lastlogin, statushistory, otherinfo) =
(EXCLUDED.creationdate, EXCLUDED.status, EXCLUDED.managedby, EXCLUDED.name, EXCLUDED.email, EXCLUDED.lastlogin, EXCLUDED.statushistory, EXCLUDED.otherinfo)"""
set (creationdate, status, name, email, lastlogin, statushistory, otherinfo) =
(EXCLUDED.creationdate, EXCLUDED.status, EXCLUDED.name, EXCLUDED.email, EXCLUDED.lastlogin, EXCLUDED.statushistory, EXCLUDED.otherinfo)"""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update of the managedby field can break available information about the provider of existing users.

We should not be allowed to replace existing users' managedby value because it is subject to very specific user-management logic e.g. a user can exist in the users static configuration file but also be managed by an external provider

…mapping settings should be exposed

Fixes #24230: Authentication providers and role mapping settings should be exposed
@clarktsiory
Copy link
Contributor Author

PR updated with a new commit

…d role mapping settings should be exposed

Fixes #24230: Authentication providers and role mapping settings should be exposed
@clarktsiory
Copy link
Contributor Author

PR updated with a new commit

final case class AuthBackendProviderProperties private (
hasAdditionalRoles: Boolean,
overridesRoles: Boolean,
hasModifiablePassword: Boolean
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the logic here is not clear (or I don't understand it).
LDAP does not have updatable password by rudder: they are managed by the LDAP directory, out of Rudder domain of responsibility.
But if we have a configuration with provider = ldap, file, ie first trying LDAP, then trying file, then we want to let the user password for the file case be updatable.
But file is not defined as an AuthBackendProviderProperties. Why so ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the hasModifiablePassword should be renamed canProviderBeMigratedToFile because that is what happens with LDAP...

I didn't really want to introduce this boolean, but its sole purpose is to allow the UI to "force" a password for an external provider (which LDAP is), as in this Elm code : https://github.com/clarktsiory/rudder-plugins/blob/bug_24219/display_user_detail_using_information_from_database/user-management/src/main/elm/sources/View.elm#L144.

Indeed with provider = ldap, file we want to let the user password for the file case be updatable, but we don't want it to be updatable with provider = oidc, file (unless I was misunderstanding the spec), so a boolean attribute for making distinction between both would be actually needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file is always handled very specifically even in the UI, so I didn't want to abstract all the properties that make the distinction between file and other providers, and I guess there are plenty...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can completely have provider = oidc, file with updatable passwords safe oidc provisioning is set to true (for at least one provider, because I don't think can know from which oidc provider users come... Which is perhaps a problem in fact - for that case, and for the case where a new OIDC provider is added or an old one removed...).
Ok, appart that new interesting subject: an oidc provider without auto-provisioning is almost exactly like LDAP conceptually: user are declared in rudder-users.xml, but the authentication is done by some other entity.

And LDAP could, one day, with lots of incentives, get an auto-provisioning mode.

ApplicationLogger.error(
s"Backend provider properties for '${name}' are not consistent: backend does not enables providing roles but roles overrides is set to true. " +
s"Overriding roles will not be enabled."
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need to do that kind of check, then it means that you are not enforcing "Make invalid states unrepresentable", which we really want to enforce as much as possible.

You likely want an ADT like:

sealed trait RoleExtension
object RoleExtension {
  case object None extends RoleExtension
  case object NoOverride extends RoleExtension
  case object WithOverride extends RoleExtention
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus with such an AST, it's easy to build an order relationship (for ex, add a priority index sealed trait RoleExtension { def index: Int } and compare on it for the priority rules, or take the max, etc)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks for the suggestion, I would only need to move the existing definition from the user-management plugin to here in Rudder : Normation/rudder-plugins@b8cd1a9#diff-50791aeada8e5190976dae763b438a4d990a8a3bbcf23b7e063a7c9ac11274c0R94-R101

@fanf
Copy link
Member

fanf commented Feb 29, 2024

Even with the feedbacks, I will merge that so that it's easier to iterate (it becomes complicated with severa PR here and on plugin). Opening an other ticket to track needed enhancements.

@fanf fanf merged commit ed0a64c into Normation:backports/7.3.12/24146 Feb 29, 2024
5 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants