Skip to content

Conversation

@shiv-tyagi
Copy link
Contributor

@shiv-tyagi shiv-tyagi commented Feb 7, 2025

As discussed in #640, this adds a property to the UserDB to mark a user enable/disabled. Before creating an authentication session in pam, we check if the user exists in the cache and is disabled.

This also adds the initial implementation of the authctl tool which can be used to enable/disable a user.

UDENG-8188

@shiv-tyagi shiv-tyagi requested a review from a team as a code owner February 7, 2025 16:14
@shiv-tyagi
Copy link
Contributor Author

@adombeck Does this look good?

I see that the tests are failing on main branch as well. So I am hoping that it is not me.

@codecov-commenter
Copy link

codecov-commenter commented Feb 7, 2025

Codecov Report

❌ Patch coverage is 76.78571% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.90%. Comparing base (229aa56) to head (3585468).
⚠️ Report is 23 commits behind head on main.

Files with missing lines Patch % Lines
cmd/authctl/main.go 30.76% 9 Missing ⚠️
internal/users/db/migration.go 83.33% 4 Missing ⚠️
cmd/authctl/user/user.go 72.72% 3 Missing ⚠️
cmd/authctl/user/lock.go 71.42% 2 Missing ⚠️
cmd/authctl/user/unlock.go 71.42% 2 Missing ⚠️
internal/services/pam/pam.go 75.00% 2 Missing ⚠️
internal/services/user/user.go 85.71% 2 Missing ⚠️
internal/users/db/update.go 80.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #782      +/-   ##
==========================================
- Coverage   88.10%   87.90%   -0.21%     
==========================================
  Files          85       89       +4     
  Lines        6013     6125     +112     
  Branches      111      111              
==========================================
+ Hits         5298     5384      +86     
- Misses        659      685      +26     
  Partials       56       56              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shiv-tyagi shiv-tyagi changed the title Check is a user is disabled before logging in Check if a user is disabled before logging in Feb 10, 2025
@adombeck
Copy link
Contributor

Hi @shiv-tyagi, yes this looks good, thanks! One small thing: I would prefer to have a Disabled field instead of Enabled, so that the default value (false) means that the user is enabled, even when we're not using NewUserDB to instantiate the UserDB struct (like we do here).

@adombeck
Copy link
Contributor

There should also be a new test case "Error_when_user_is_disabled" in https://github.com/shiv-tyagi/authd/blob/fed39218cfcce6c23e80e0d02fe2a2d748d3d912/internal/brokers/manager_test.go#L187-L190.

@adombeck
Copy link
Contributor

Oh and I don't think it makes sense to merge this before we have code which actually causes a user to be disabled (i.e. the command-line tool). If you still plan to work on that soon, feel free to repurpose this PR. Otherwise, I'll start working on that soon and would then cherry-pick your commits to a new branch.

@shiv-tyagi
Copy link
Contributor Author

I would prefer to have a Disabled field instead of Enabled, so that the default value (false) means that the user is enabled, even when we're not using NewUserDB to instantiate the UserDB struct (like we do here).

Sure. I will do that.

There should also be a new test case "Error_when_user_is_disabled"

Noted.

If you still plan to work on that soon, feel free to repurpose this PR.

Yes, I really intend to work on that. I will push my work soon :)

@shiv-tyagi shiv-tyagi force-pushed the user-disable branch 4 times, most recently from 7183092 to 5e81b35 Compare February 15, 2025 18:22
@adombeck
Copy link
Contributor

I rebased on main and resolved the conflicts caused by #779.

@shiv-tyagi
Copy link
Contributor Author

I rebased on main and resolved the conflicts caused by #779.

Thanks for this @adombeck. I had some more work which I had not pushed yet. I would need to fix that as well. Planning to push that work soon.

@shiv-tyagi shiv-tyagi force-pushed the user-disable branch 2 times, most recently from 7f1338f to fce5e88 Compare February 19, 2025 06:51
@shiv-tyagi
Copy link
Contributor Author

I have finished the part till extending the GRPC API with new methods and adding unit tests for those. Now only the part of creating the CLI tool to call those methods remains.

@shiv-tyagi shiv-tyagi changed the title Check if a user is disabled before logging in Add functionality to Enable/Disable users Feb 26, 2025
@shiv-tyagi
Copy link
Contributor Author

@adombeck I have added the initial implementation of the authctl tool. Please check if it looks good and provide any suggestions for me to proceed. This is my first time writing Go code, so I apologise if I made any rookie mistakes. I’ll be happy to fix them.

Thanks in advance.

Copy link
Contributor

@adombeck adombeck left a comment

Choose a reason for hiding this comment

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

I've got a few comments but the overall code style is good! Thanks a lot, @shiv-tyagi!

@shiv-tyagi
Copy link
Contributor Author

Thank you so much @adombeck for reviewing this. I have addressed all your suggestions. What next? How should I test it locally?

adombeck and others added 25 commits September 23, 2025 15:24
I don't know why, but specifying "Args: cobra.NoArgs" without a Run or
RunE function has this effect.
I would expect a function called RunDaemon to start the daemon and block
until it has finished running. StartDaemon makes it clear that the
function returns once the daemon was started.
It can take a while to build and start the daemon. Lets add some logs to
make it a bit clearer what is taking so long.
authctl shows these errors messages, so let's improve them.
For example, instead of:

    no result matching "foo" in "users"

use:

    user "foo" not found
The BuildDaemon() function is only called to build the daemon for
integration tests with the example broker. Lets avoid passing the same
arguments everywhere.

Also renames the function to BuildDaemonWithExampleBroker.
Everywhere we called StartDaemon(), we registered the cleanup of the
daemon process via t.Cleanup(). Let's avoid the duplicate code by
inlining the cleanup registration into StartDaemon().
Lets be more consistent with other command-line tools which control
system services, like systemctl and machinectl, and not print any output
if the command succeeds (for example like `systemctl start`/`systemctl stop` or
`machinectl kill`).
When trying to log in with a locked user, the following error message is
printed:

    $ su [email protected]
    can't select broker: error PermissionDenied from server: can't start authentication transaction: rpc error: code = PermissionDenied desc = user [email protected] is locked

The "can't start authentication transaction" part doesn't add any
valuable information to the error message, which is already too long.

By omitting it, we also avoid that the gRPC status is formatted to a
string containing the error code, which would duplicate information
which the caller adds to the error message.

With this commit, the error message is simplified to:

    can't select broker: error PermissionDenied from server: user [email protected] is locked
Following up on the error message printed when trying to log in as a
locked user, we can further improve the message:

    $ su [email protected]
    can't select broker: error PermissionDenied from server: user [email protected] is locked

by omitting the "can't select broker:" part, which doesn't add any
useful information.

With this commit, the error message is simplified to:

    error PermissionDenied from server: user [email protected] is locked
Further improve the error message printed when trying to log in with a
locked user from:

    error PermissionDenied from server: user [email protected] is locked

to
    permission denied: user [email protected] is locked
Same as pam_unix, we now avoid leaking to unauthenticated users whether
a user account is locked. That's achieved by only checking if the user
is locked after they successfully authenticated to the broker, aborting
login in that case.

That has the side effect that locked users can still refresh the token
and user info which the broker stores on disk.

This commit also implements the same improvements to the "permission
denied: user is locked" error message which were already implemented in
the SelectBroker method. I'm not reverting the changes to the
SelectBroker method because I think they are still improvements, even if
they are not relevant for this specific error message anymore.
@adombeck adombeck merged commit a91dc7f into ubuntu:main Sep 23, 2025
10 of 13 checks passed
@adombeck
Copy link
Contributor

Many thanks for the great contribution, @shiv-tyagi!

@shiv-tyagi
Copy link
Contributor Author

Finally!!! Really happy.

Thanks to you @adombeck as you did most of the work and kept it alive. Grateful to you. I will continue contributing :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants