Gunnar

nordisk/holger

.nornir/auth-for-idiots.md

# Locking holger's front door — for idiots

> **Class:** `idiot`. Every step spelled out. Goal: take a holger that lets **anybody**
> upload and turn it into one where only people you name can. If you know RON, read
> [`auth-guide.md`](auth-guide.md) instead.

## The one thing to understand first

Fresh out of the box, holger's front door is **unlocked**: with no security settings,
*anybody* who can reach it can upload packages. That is fine for a toy on your own laptop,
and dangerous on a network. Locking it is two switches in one config file.

## Where the config file is

Holger reads a file called `holger.ron`. In a running deployment it is the `configmap` in
your Kubernetes setup; on your laptop it is whatever file you pass to
`holger-server start --config <file>`. Open that file in a text editor.

## Switch 1 — require a login

Find (or add, near the top) a block named `auth`. Make it look like this — this says
"callers must prove who they are, with either a certificate or a token":

```
auth: Some((
    methods: [
        Oidc(( issuer_url: "https://idp.example.com/realm" )),
        Mtls(( ca_cert: "/etc/holger/ca.pem" )),
    ],
)),
```

- `Oidc` = a token from your identity provider (like a company login).
- `Mtls` = a certificate. Point `ca_cert` at the certificate authority file that signs
  your clients' certificates.

You can keep just one of the two lines if you only use one. Save the file.

## Switch 2 — hand out roles

Still inside the `auth` block, add a `roles` list and a `default_role`. This is the switch
that actually locks the door:

```
auth: Some((
    methods: [ /* the lines from Switch 1 */ ],
    roles: {
        "alice@corp":   Admin,
        "CN=build-bot": Writer,
    },
    default_role: Some(Reader),
)),
```

- Each line maps **who** (their login name or certificate name) to **what they may do**:
  `Reader` (download only), `Writer` (upload), or `Admin` (upload + delete).
- `default_role: Some(Reader)` means "anyone I did not list can only read." That is what
  makes the door locked-by-default: only the names you wrote as `Writer`/`Admin` may upload.

Save the file. The moment holger sees a `roles` list, it flips into locked-by-default:
uploads need `Writer` or `Admin`, deletes need `Admin`, anyone not listed (or not logged
in) is turned away, and readers can still download.

## Restart and check

Restart holger so it re-reads the file (in Kubernetes, roll the deployment; on your laptop,
stop and start `holger-server`). Now try to upload **without** a credential — it should be
refused. Try again as a listed `Writer` — it should work.

## The rule to remember

Until you have set **both** switches, treat the server as **open** — only run it that way
somewhere already private. And even with the switches on, the safest shape is: don't let
people upload to the server at all — pack packages on the *outside* with the agent and
carry them in ([`agent-guide`](agent-guide.md)).

## Do downloads need a login too?

By default, **no**. Anyone who can reach holger can download. That sounds alarming until
you remember where holger usually lives: inside a locked room, on the safe side of an
airgap. Getting to the network at all *was* the security check. And it has to work that
way — `pip install` and `cargo build` have nowhere to type a password.

If your holger is somewhere less private — a normal office network, or the *names* of
your repositories are themselves a secret — you can require a login for downloads too.
One line:

```ron
require_auth_for_reads: true,
```

Then downloads work like uploads: no login, no download. Add it next to the `methods`
and `roles` you already set up (see `auth-guide.md` D.7).

Two things worth knowing before you flip it:

- **You must have a login method configured.** If you turn on "downloads need a login"
  but never told holger *how* anyone logs in, then nobody can log in, so nobody can
  download anything. Holger prints a big warning at startup when you do this. It is
  refusing on purpose — that is safer than quietly letting everyone in — but it is
  still you locking yourself out.
- **Health checks keep working.** The little "are you alive?" URLs stay open, so your
  load balancer and your monitoring do not fall over the moment you flip the switch.

There is also a `Denied` setting you can give a person for one specific repository. It
means exactly what it says: everything else is readable to them, that one is not.

And a nice side effect: once downloads have a login, the log stops saying "somebody"
and starts saying *who*. If you ever need to answer "who pulled that build", that is
the switch that makes the answer exist.