PAM lines written into login and passwd as blocks, so login unlocks the keyring on both workstations; no daemon of its own; gcr's ssh agent named for the session until the environment can say a runtime-directory path. Go tools unlocked, lock, collections and ssh-keys, never reading a secret.
102 lines
5.6 KiB
Markdown
102 lines
5.6 KiB
Markdown
# gnome-keyring
|
|
|
|
The secret service as a module (novox/hq ADR 0208, ADR 0102).
|
|
|
|
- Installs `gnome-keyring` (it brings `gcr-4`, whose ssh agent this uses), `libsecret` (the client
|
|
library and `secret-tool`) and `seahorse` (the keyrings' manager, for the operator).
|
|
- Claims the mesh's `node-secret-service` seat (no verbs yet, ADR 0208 §2). It requires no display:
|
|
the secret service is a D-Bus service, and a Wayland session uses the same module.
|
|
- **Writes the PAM lines into the stacks, never over them** (ADR 0102). Each is a marked block at the
|
|
end of the file; every other line stays the distribution's.
|
|
- `/etc/pam.d/login`: `auth optional pam_gnome_keyring.so` and
|
|
`session optional pam_gnome_keyring.so auto_start`. The login manager's stack includes `login`,
|
|
so the password typed at the login screen unlocks the login keyring, and the login session starts
|
|
the daemon.
|
|
- `/etc/pam.d/passwd`: `password optional pam_gnome_keyring.so`, so changing the account's password
|
|
changes the keyring's, and the next login still unlocks it.
|
|
- **Starts no daemon.** PAM starts it at login, and D-Bus would if PAM had not.
|
|
- Names gcr's ssh agent socket for the session, in the `xinitrc` slot `first`: `SSH_AUTH_SOCK` is
|
|
`$XDG_RUNTIME_DIR/gcr/ssh`. The agent itself is `gcr-ssh-agent.socket`, a user unit the package
|
|
enables by preset.
|
|
|
|
## Tools
|
|
|
|
None reads a secret. They ask the Secret Service for names, counts and lock states, and the agent for
|
|
fingerprints.
|
|
|
|
| tool | does |
|
|
|---|---|
|
|
| `gnome_keyring_unlocked` | the login and default keyrings, locked or not; whether the daemon runs |
|
|
| `gnome_keyring_lock` | lock a keyring now (login by default); unlocking stays the operator's |
|
|
| `gnome_keyring_collections` | every keyring: id, label, locked, item count, created, changed, default |
|
|
| `gnome_keyring_ssh_keys` | the agent's keys by fingerprint, size, type and comment |
|
|
|
|
## What it improves on what was found
|
|
|
|
- **The desktop's login unlocks the keyring.** Its `/etc/pam.d/login` had no keyring lines, so the
|
|
keyring stayed locked after every login, and a script prompted for the password to unlock it. Both
|
|
workstations now get the same lines.
|
|
- **One daemon.** The session's start ran `gnome-keyring-daemon --start` a second time, asking for an
|
|
ssh component that gnome-keyring no longer has, and the window manager ran an unlock-prompt script.
|
|
Both go.
|
|
- **The session has an ssh agent.** The found `export SSH_AUTH_SOCK` exported nothing: the second
|
|
daemon printed no socket. The session's processes had no agent, although gcr's was listening.
|
|
|
|
## The default keyring is not the login keyring
|
|
|
|
On both workstations, measured on 2026-10-04, the default keyring, where programs store new secrets,
|
|
is a second keyring, `Default_keyring`. The login keyring holds one item at most. PAM unlocks only the
|
|
login keyring. Another keyring opens with it only if its password is stored in the login keyring
|
|
("unlock automatically"). On the desktop the login keyring was locked and the default one unlocked,
|
|
which the unlock-prompt script did.
|
|
|
|
After the first login with this module: `gnome_keyring_unlocked` shows both. If the default keyring
|
|
is still locked, choose one, once, in `seahorse`:
|
|
|
|
- tick its *unlock automatically* when prompted;
|
|
- or move its items into the login keyring and make that the default.
|
|
|
|
Which keyring is the default is the operator's data, never the module's.
|
|
|
|
## Blockers and a proposal
|
|
|
|
**`SSH_AUTH_SOCK` belongs in the account's environment, and ADR 0203 cannot say it yet.** The value
|
|
is a path under the account's runtime directory (`/run/user/<uid>`). ADR 0203 forbids `$` in a
|
|
contributed value, and no `${machine:…}` fact names that directory. So today the variable reaches
|
|
only the X session and what it starts, through the `xinitrc` slot. An ssh login, the login shell's
|
|
`execute` and the user manager's services do not get it.
|
|
|
|
**Proposed:** a machine fact `${machine:account-runtime-dir}`, resolved like `${machine:account-home}`
|
|
from the account's uid. The variable then becomes an environment contribution:
|
|
|
|
> `environment.variables.SSH_AUTH_SOCK` = `${machine:account-runtime-dir}/gcr/ssh`
|
|
|
|
The slot contribution then goes. That is a progressive insight on ADR 0203, or a small record of its
|
|
own. It changes the controller's machine facts, not this module's shape.
|
|
|
|
**User-scoped units (mesh-host #72).** `gcr-ssh-agent.socket` and `gnome-keyring-daemon.socket` are
|
|
enabled by the package's presets on both workstations, and nothing in the mesh asserts it. Once user
|
|
units ship, this module should declare both enabled.
|
|
|
|
## What it leaves as found
|
|
|
|
- The keyrings themselves (`~/.local/share/keyrings/`): the operator's data, never touched.
|
|
- `~/.config/i3/unlock-keyring.sh`, the unlock-prompt script.
|
|
|
|
## Migration (ADR 0182)
|
|
|
|
1. **On the laptop,** `/etc/pam.d/login` already has the two lines outside any block. After the first
|
|
push they are there twice. Delete the two hand-written ones, outside the `# BEGIN mesh` block.
|
|
2. Once the `xorg` module writes the session's start, delete from your own part of `~/.xinitrc` the
|
|
`eval $(/usr/bin/gnome-keyring-daemon --start …)` line and the `export SSH_AUTH_SOCK` after it.
|
|
3. Once the `i3` module carries the main configuration, its `exec … unlock-keyring.sh` line is gone.
|
|
Delete `~/.config/i3/unlock-keyring.sh`.
|
|
4. **On the desktop,** log in again after the first push. The keyring is unlocked by the login from
|
|
then on.
|
|
|
|
## Blockers
|
|
|
|
- `node-secret-service` and the `xinitrc` slot are ADR 0208's. Until the controller knows them,
|
|
`mctl` reads them as unknown.
|
|
- The environment fact above, and user-scoped units (mesh-host #72).
|