146 lines
6.6 KiB
Markdown
146 lines
6.6 KiB
Markdown
# Getting started: bringing your people in
|
|||
|
|
|
||
|
|
A site is run by a handful of people: whoever answers for each question
|
||
|
|
it asks, and whoever works each desk. This is how they get in - from
|
||
|
|
an empty Kanidm to everyone signed in at their own desk - without
|
||
|
|
anyone handing out passwords or running an admin tool per person.
|
||
|
|
|
||
|
|
The idea in one line: **the content says who is involved, and portal
|
||
|
|
makes their accounts.** A page names who is responsible for it; a
|
||
|
|
directory is gated on a group; a desk may invite into groups. Portal
|
||
|
|
reads that and does the rest at start.
|
||
|
|
|
||
|
|
## What you need
|
||
|
|
|
||
|
|
- A content repo, and a portal instance running it
|
||
|
|
([Operations](operations.md) has adding a site).
|
||
|
|
- A Kanidm of the site's own. Group names below are exactly the ones
|
||
|
|
the content uses, with no prefix; that is only safe when the Kanidm
|
||
|
|
serves this site alone.
|
||
|
|
- Mail: `mail: { from }` in `site.yaml`, and gdo on the host. Without
|
||
|
|
it accounts are still made, but nobody hears about them.
|
||
|
|
|
||
|
|
## 1. Say who is involved, in the content
|
||
|
|
|
||
|
|
Three things in the content decide who needs an account:
|
||
|
|
|
||
|
|
| content | who | what they get |
|
||
|
|
|---|---|---|
|
||
|
|
| `responsible: { name, contact }` on a page | the person answering for that question | an account, and a mail saying they are listed as responsible for asking it |
|
||
|
|
| `qualifies: styret` on a page or `_section.yaml` | members of that group | the pages and desks under it |
|
||
|
|
| `invite: { group: kasserer }` on a desk page | the desk's own group | the right to bring people into `kasserer` |
|
||
|
|
|
||
|
|
The desk whose group may invite into the most groups is the site's most
|
||
|
|
privileged one; on a vel that is the board. Portal works that out from
|
||
|
|
the content (see step 4).
|
||
|
|
|
||
|
|
## 2. Set up Kanidm for portal
|
||
|
|
|
||
|
|
Portal needs four things from Kanidm. The
|
||
|
|
[tomtervel/infrastructure](https://prosjekt.klingenbergbygg.no/tomtervel/infrastructure)
|
||
|
|
repo's `kanidm-setup.sh` does all of them and is a good starting point;
|
||
|
|
by hand, as `idm_admin`:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
K="kanidm -D idm_admin -H https://id.example.no"
|
||
|
|
|
||
|
|
# An onboarding account: may create people and issue a first password
|
||
|
|
# link, nothing more. pii_read lets an invite find someone who already
|
||
|
|
# has an account by their email instead of making a second one.
|
||
|
|
$K service-account create portal-onboarding "Portal onboarding" idm_admin
|
||
|
|
$K group add-members idm_people_on_boarding portal-onboarding
|
||
|
|
$K group add-members idm_people_pii_read portal-onboarding
|
||
|
|
|
||
|
|
# One group per `qualifies:` in the content, managed by that account:
|
||
|
|
# adding a member to a group takes the right to manage it.
|
||
|
|
for g in styret kasserer trafikk; do
|
||
|
|
$K group create "$g" portal-onboarding
|
||
|
|
done
|
||
|
|
|
||
|
|
# The sign-in client. Everyone in this Kanidm may sign in; what they
|
||
|
|
# see comes from their groups, in the `groups` claim.
|
||
|
|
$K system oauth2 create portal "My site" https://site.example.no
|
||
|
|
$K system oauth2 add-redirect-url portal https://site.example.no/auth/callback
|
||
|
|
$K system oauth2 update-scope-map portal idm_all_persons openid profile email
|
||
|
|
for g in styret kasserer trafikk; do
|
||
|
|
$K system oauth2 update-claim-map portal groups "$g" "$g"
|
||
|
|
done
|
||
|
|
$K system oauth2 update-claim-map-join portal groups array
|
||
|
|
|
||
|
|
# The onboarding token, read-write, shown once: into portal's env.
|
||
|
|
$K service-account api-token generate portal-onboarding portal --readwrite
|
||
|
|
```
|
||
|
|
|
||
|
|
Then portal's environment:
|
||
|
|
|
||
|
|
| variable | value |
|
||
|
|
|---|---|
|
||
|
|
| `KANIDM_URL` | `https://id.example.no` |
|
||
|
|
| `OAUTH2_CLIENT_ID`, `OAUTH2_CLIENT_SECRET` | the client above (`show-basic-secret`) |
|
||
|
|
| `KANIDM_API_TOKEN` | the onboarding token |
|
||
|
|
|
||
|
|
## 3. Name the first person
|
||
|
|
|
||
|
|
Someone has to be first: every later person is invited from a desk,
|
||
|
|
and on an empty Kanidm there is no desk anyone can open yet.
|
||
|
|
|
||
|
|
| variable | value |
|
||
|
|
|---|---|
|
||
|
|
| `SEED_ADMIN_EMAIL` | the first person's address |
|
||
|
|
| `SEED_ADMIN_NAME` | their name, as it should appear (optional) |
|
||
|
|
| `SEED_GROUP` | a group to put them in, if not the most privileged one (optional) |
|
||
|
|
| `RESPONSIBLE_GROUP` | a group every responsible person joins, e.g. `redaktor` (optional) |
|
||
|
|
|
||
|
|
## 4. Start portal
|
||
|
|
|
||
|
|
At start, portal:
|
||
|
|
|
||
|
|
1. **Invites the first person** into `SEED_GROUP`, or the most
|
||
|
|
privileged group, and mails them the one-time link. Once: it is
|
||
|
|
remembered in the `portal_seed` bucket, so restarts and upgrades
|
||
|
|
never send a second link.
|
||
|
|
2. **Makes an account for everyone named responsible** who has none,
|
||
|
|
and mails them that they are listed as responsible for asking those
|
||
|
|
questions, with their link. With `RESPONSIBLE_GROUP` they all join
|
||
|
|
it; someone who already had an account is added without a mail.
|
||
|
|
|
||
|
|
Kanidm may still be starting beside portal, so a failed attempt is
|
||
|
|
tried again, a minute apart. The log says what happened, per person.
|
||
|
|
|
||
|
|
## 5. The rest come in from the desks
|
||
|
|
|
||
|
|
From here nobody touches Kanidm:
|
||
|
|
|
||
|
|
- **At a desk**, whoever may invite fills in a name and an address.
|
||
|
|
Portal makes the account, adds them to the group, and mails the link.
|
||
|
|
The invites sent are listed on that desk.
|
||
|
|
- **A decision can be the invitation.** A state with `grants: group`
|
||
|
|
in `aggregates.yaml` puts the person a case is about into that group
|
||
|
|
when the case arrives there - an approved committee application that
|
||
|
|
*is* the membership.
|
||
|
|
- **A new page with a new responsible person** gets them an account at
|
||
|
|
the next start.
|
||
|
|
|
||
|
|
## 6. What the people who ask the questions can do
|
||
|
|
|
||
|
|
Signed in, a person a page names as responsible sees a card at the
|
||
|
|
foot of their own pages to suggest a change. The server checks it is
|
||
|
|
really them; the suggestion is kept (`portal_edit_suggestions`),
|
||
|
|
announced (`portal.edits.suggested`), and mailed to the site's inbox
|
||
|
|
with them as reply-to, so answering it answers them.
|
||
|
|
|
||
|
|
Their group can also be the way into other tools. The vel's
|
||
|
|
`redaktor` group signs in to the project Gitea with the same account:
|
||
|
|
a second OAuth2 client scoped to that group alone.
|
||
|
|
|
||
|
|
## When it does not work
|
||
|
|
|
||
|
|
| what you see | why |
|
||
|
|
|---|---|
|
||
|
|
| an invite fails with `403` setting `mail` | a portal before 0.5.4 set the address in a second call; the onboarding account may create but not modify |
|
||
|
|
| an invite fails with `404` adding to a group | the group is not managed by `portal-onboarding`: `group set-entry-manager <group> portal-onboarding` |
|
||
|
|
| `Item not found` setting the login page's name or logo | those are system settings only `admin` may change, not `idm_admin` - or the CLI and server versions differ |
|
||
|
|
| accounts are made but nobody is mailed | `site.yaml` has no `mail.from`, or gdo is not running on the host |
|
||
|
|
| someone responsible never got a mail | they already had an account (they are only added to `RESPONSIBLE_GROUP`), or their `contact` is not an email address |
|
||
|
|
| the first person was invited twice | it cannot be, per address and group; changing `SEED_ADMIN_EMAIL` or `SEED_GROUP` invites the new pair |
|