bf952a5dc4
This works, however there's still stuff to do. The configuration.nix pam stack is broken, still defaults back to pam_unix.so if this fails. The code is now a small mess, I need to make `Client` structs and more separation. And I still have to fully understand keycloak and properly use the clients or configure them.
91 lines
4.6 KiB
Markdown
91 lines
4.6 KiB
Markdown
# keycloak-pam
|
|
|
|
Tiny PAM module to perform authentication against a keycloak instance.
|
|
|
|
Testing and development are done within a nix environment, if you don't plan to use nix extract the pieces you care about, but we only support nix configuration.
|
|
|
|
# System Configuration
|
|
|
|
This is being worked on, refer to the test configuration at [`tests/nixos/configuration.nix`](./tests/nixos/configuration.nix).
|
|
|
|
# Arguments
|
|
|
|
Module can be easily configured with PAM arguments, for the sake of completeness refer to the source code.
|
|
|
|
You can `cargo doc` to find the documentation for this at `keycloak_pam > args > Args`.
|
|
|
|
# Restrictions and Guarantees
|
|
|
|
With the purpose of being tiny and minimal, the module uses libcurl for the few requests it makes, so HTTP/S and all networking behavior is offloaded to it.
|
|
|
|
This is also made in rust, which means default `String` and `&str` are guaranteed to be UTF-8 encoded and invalid UTF-8 input might fail. I did try to use OS and C strings for all input, but I recommend still avoiding non-UTF8 input. Password change needs to convert to `String` at some point and UTF-8 input is required.
|
|
|
|
The code should **NEVER** panic (aside from memory management issues), no `unwrap`, `expect` or such methods should ever be used, slice indexing is avoided and errors are gracefully managed.
|
|
|
|
To check the group, keycloak-pam uses libc's `getgrnam_r`, this takes a buffer we hardcoded to 4 KiB, if there happens to be a group bigger than this, keycloak-pam won't be able to handle and will fail explaining this.
|
|
|
|
# Policy
|
|
|
|
Keycloak can be configured in a lot of ways, so it's important to understand how this module will interact with Keylcoak. Otherwise misconfiguration can allow anyone to login as another user.
|
|
|
|
Think of this as stages, where the first one for all actions is:
|
|
|
|
Must check the subject user against the configured group. If it's not a member, it will just fallback to the next PAM module.
|
|
|
|
Here things differ a bit from login to password change:
|
|
|
|
## Login
|
|
|
|
This is simple, will only allow login if the password used to log in is not temporary, any error will fail with an error.
|
|
|
|
The client used for this is still not definitive, currently it uses a client ID and client secret for this, `account` by default, but this might change.
|
|
|
|
## Registration
|
|
|
|
Even then, a user might and should be able to login if their account is not set up (e.g. through ssh).
|
|
|
|
If they try to change their password without having one set up, it won't ask for their current one and will use the admin REST API to set the first one, this one won't be a temporary password and will fully set up their accounts.
|
|
|
|
# Behavior
|
|
|
|
To authenticate users, the module uses the endpoint `{BASE_URL}/realms/{realm}/protocol/openid-connect/token` as a configured client. This needs a client ID and its secret that you need to get and configure per realm.
|
|
|
|
A curl request you can use anywhere to test this is:
|
|
|
|
```
|
|
curl -X POST http://keycloak-pam.test/realms/master/protocol/openid-connect/token \
|
|
-d grant_type=password \
|
|
-d username=admin \
|
|
-d password=dontchangeme \
|
|
-d client_id=account \
|
|
-d client_secret=7bsrMrRuNKpqsxcOOJavWjEqek12ZCkj
|
|
```
|
|
|
|
The secret and id there are just an example (`account` is a client configurd by default by keycloak).
|
|
|
|
This is the simplest way to check credentials but also has the consequence of leaking unhandled oauth2/OIDC user tokens. I'm unsure if this could have further consequences but it's a risk worth considering.
|
|
|
|
# Development
|
|
|
|
The nix test configuration relies on bridging the VM IP, for this it relies on the default `libvirt`'s interface and needs the `qemu-bridge-helper`. This is found in a nix shell hook.
|
|
|
|
To have the necessary environment you should nix-develop in the shell, which will also provide the proper rust version and components.
|
|
|
|
You should also have `libvirt` configured on your system, other virtualization methods are not supported, if you have interface issues try to `virsh net-start default/virbr0`.
|
|
|
|
The test configuration treats itself as `keycloak-pam.test`, you might be interested in adding this to your `/etc/hosts` if you are going to use its web interface much.
|
|
|
|
# Rust Version
|
|
|
|
The project is meant to work under rust stable.
|
|
|
|
No specific MSRV is given, but if it compiles it should work.
|
|
|
|
# License
|
|
|
|
This code is meant to be used for [tuxcord.nix](https://git.javalsai.tuxcord.net/tuxcord/tuxcord.nix/issues), it copies some of such configuration and follows its same license.
|
|
|
|
This is **exclusively** licensed under the GNU Lesser General Public License (`LGPL-3.0-only`).
|
|
|
|
You are allowed to modify and redistribte derivatives of this work provided you comply with the license.
|