keycloak-allowban-plugin/README.md

114 lines
3.8 KiB
Markdown

# Keycloak allow/ban plugin
This is a plugin for Keycloak that checks an allow-list and a ban list for
users from GitHub.
## Configuration
Add the plugin to your keycloak plugins list. The plugin can be obtained via
`nix build .#packages.default`.
The configuration of this plugin is in a directory of text files with the
format `github-id github-username`, allowing `#` comments.
Specify a Keycloak config file option
`spi-authenticator-allow-ban-check-authenticator-dbpath` pointing to the
directory with the configuration. Note that the error if you don't configure
this is complete garbage, and is also not printed by default (sorry)! Use
`kc.sh --verbose start` to read your `NullPointerException`.
There are three notable files in there:
- `banned-users.txt`: contains a list of GitHub IDs which will be rejected
outright on login.
If you newly ban a user, you have to kill all their sessions across all
infrastructure, including existing Keycloak sessions, since bans only apply
on login.
- `allowed-users.txt`: contains a list of GitHub IDs which will be allowed if the
allow-list is enabled.
- `use-allow-list.txt`: if present, the allow-list mechanism is used. Otherwise
it is bypassed and all logins are allowed.
The intent of the configuration is that it is synced by a cron job pulling a
git repo.
## Setup
1. In the GitHub Identity Provider configuration on Keycloak, set up a mapper with
type "Attribute Importer", importing the JSON field path "id" as a user
profile attribute "githubId".
2. Create an auth flow for post login on the identity provider, containing one
element "Allow/Ban check". This is necessary since it bypasses the standard
login flow if you log in via the external IdP.
3. In the identity provider, set the *Post Login Flow* to the flow just
created.
4. Add the "Allow/Ban check" action to the main login flow as a Required
element at a point *after* the username is determined.
## Notes
We are unsure if Store Tokens is necessary to set; it is not for this plugin,
but it might be a good idea to simply have them around.
We don't think there are ways to ban-evade, since this is managed by a
user-invisible profile attribute that is permanently glued to all accounts
originating from GitHub.
We have tested this on Keycloak 23 and 24.
### Test environment!
There is a test environment included with this plugin to avoid testing in prod.
Run:
```
nix run .#
```
Then in a separate terminal:
```
sudo socat TCP-LISTEN:443,fork,reuseaddr TCP:127.0.0.1:4043
```
and add `127.0.0.1 identity.test.lix.systems` to `/etc/hosts`. Dump Firefox
DNS cache if necessary (`about:networking`), and create a GitHub OAuth app.
You can ssh into the machine on port 2022 on localhost as root, with no
password.
Then finally go to `https://identity.test.lix.systems/superadmin`, and log in
with `admin`/`Password1`.
### Attaching a debugger to Keycloak
We are so sorry.
If you are doing this to the VM here, change the last line of the keycloak
startup script to this:
`DEBUG=true DEBUG_PORT='*:1337' DEBUG_SUSPEND=y kc.sh --verbose start --optimized --debug`
To actually make that work, you want to copy the file from `systemctl cat
keycloak.service` to `/start-keycloak`, then `systemctl edit --runtime
keycloak`, with the contents:
```
[Service]
ExecStart=
ExecStart=/start-keycloak
```
Then `systemctl restart keycloak`. Next create a forward like `ssh
-L1337:localhost:1337 localvm` and attach your Java debugger to port 1337.
### Future steps
We might need to do account age stuff, if we get sockpuppet problems.
Note this also: https://keycloak.discourse.group/t/retrieve-identity-provider-github-token/16613
Also, the GitHub IdP mappers get all of this response's info, including account age: https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user