packages feed

pi-hoole-0.2.0.0: README.md

# pi-hoole

`pi-hoole` is a collection of tools to enforce access control for self-hosted
pijul repositories. It can be seen as a cgit-like solution, for authenticated
(public key, SSH) and anonymous accesses. You can grant read and write accesses
to a whole repository, or to a determined subset of branches.

`pi-hoole` is distributed under the terms of the AGPL v3.

## Getting Started

### Building From Source

It should not be a surprise that `pi-hoole` is versioned under `pijul`, with the
patch format introduced by `pijul-0.9`. Fair warning, use `pijul-0.10.1` and you
should be able to clone the `pi-hoole` repository.

```bash
pijul clone https://pijul.lthms.xyz/pijul/pi-hoole
```

Under the hood, `pi-hoole` is implemented in Haskell. We will need `stack` to
build it.

```bash
cd pi-hoole
stack build
```

We are using the latest lts available, but `pi-hoole` has already been built
with `lts-10` (but does not build with older ones).

This build three executables:

* `pi-hoole-cfg` generates a `.authorized_keys` file to enforce access control
  for SSH.
* `pi-hoole-shell` is called to determine if a authenticated user is allowed to
  perform a given `pijul` command.
* `pi-hoole-web` is a HTTP proxy to enforce access control for anonymous
  requests.

### Installing

In order to use `pi-hoole` on your server, the first step is to create a new,
dedicated user (*e.g.* `pijul`). You then need to make `pijul` and
`pi-hoole-shell` available to this user. Currently, we do not provide any
packaging solution to that end, but this might change in the future. Although it
is not mandatory, we consider both `pi-hoole-cfg` and `pi-hoole-web` have also
been made available for the `pijul` user.

### Configuring

`pi-hoole` executables assume the configuration files are stored at
`${XDG_CONFIG_DIRECTORY}/pi-hoole`, that is `~/.config/pi-hoole` by default.

In this directory, `pi-hoole` will scan the `keys/` directory, if it exists,
to know the list of authorized authenticated users. One user may have as many
public key as required. Keys should be saved in file with the following filename
scheme: `<user>(\.<label>)?\.pub`. Thus, `lthms.pub`, `lthms.laptop.pub` and
`lthms.work.pub` are three valid public key filenames for the `lthms` user.

To generate a `.ssh/authorized_keys`, use `pi-hoole-cfg`.

```bash
pi-hoole-cfg generate > ~/.ssh/authorized_keys
```

Resulting file will be of the forms:

    command="pi-hoole-shell \".lthms\" \"${SSH_ORIGINAL_COMMAND}\"",no-port-forwarding,no-x11-forwarding,no-agent-forwarding <ssh_keys_1>
    command="pi-hoole-shell \".lthms\" \"${SSH_ORIGINAL_COMMAND}\"",no-port-forwarding,no-x11-forwarding,no-agent-forwarding <ssh_keys_2>

To configure the authorized accesses for the users, you have to set up a valid
`pi-hoole` configuration file. The latter uses the YAML syntax, and is located
at `${XDG_CONFIG_DIRECTORY}/pi-hoole/config.yaml`.  It has two root fields:
`groups` and `repositories`.

You can define groups of users, and grant certain rights to a group, effectively
granting there rights to each users who are member of the group.

Group names are prefixed by `+`, and user names are prefixed by `.`.

Then, if you want to create one group `ogma` which contains the users `lgeorget`
and `lthms`:

    groups:
      +ogma: [.lthms, .lgeorget]

You can create as many groups as you want, and one user may be added to several
groups. Currently, nested groups are not allowed (*i.e.* a group being member of
another group).

The `repositories` field allows for defining which repositories are available, and
what given users can do with these repositories. The contents of the
`repositories` is a map, where keys are `path` to the repositories (relative to
`HOME` directory), and values are maps from role to rights.

For instance, given the following configuration:

    repositories:
      my/first/repo:
        .lthms: +w
        +contrib: +r +w[master]
        anon: +r

      my/second/repo:
        .lthms: +r
        .lgeorget: +w

We declare two repositories, one located at `${HOME}/my/first/repo`, and another
at `${HOME}/my/second/repo`. The user `lthms` (identified with `.lthms`) can
read and write to this repository, to arbitrary branches. The members of the
group `contrib` can read to any branch, but can only write to the `master`
branch. Finally, the anonymous user (through HTTP), can read to any branch.

Read means being able to clone or pull. Write means being able to push.

For the second repository, `lthms` can read to any branch, when `lgeorget` can
read and write to any branch. Therefore, it is not possible to clone
`my/second/repo` through HTTP, because `anon` has not been granted any
particular rights.

### Setting Up HTTP Proxy

`pi-hoole-web` is a very simple HTTP proxy. It receives HTTP request, ideally
issued by a `pijul` client, and turns them into `pijul` commands if the `anon`
role has been granted the required rights.

Currently, `pi-hoole-web` cannot be configured, and listen the port 8080. Also,
it does not daemonify itself. The easiest way to set up a `pi-hoole-web`
instance in a reliable way is to use systemd, for instance with the following
unit:

```
[Unit]
Description=HTTP Proxy for Pijul anonymous accesses

[Service]
Type=simple
User=pijul
Group=pijul
ExecStart=/usr/bin/pi-hoole-web
Restart=of-failure
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target
```

For reference, the instance of `pi-hoole-web` responsible for `pijul.lthms.xyz`
is behind a nginx server. One very straightforward nginx configuration can be:

```
server {
  listen 80;
  server_name pijul.lthms.xyz;

  access_log /var/log/nginx/pijul.lthms.xyz.access.log;
  error_log /var/log/nginx/pijul.lthms.xyz.error.log;

  location / {
    proxy_pass http://localhost:8080/;
  }
}
```

For `pi-hoole-web` to work correcty, it needs an additional configuration file,
assumed to be at `${XDG_CONFIG_DIRECTORY}/pi-hoole/web.yaml`. This file is
currently very simple, it contains only three fields:

* `title`: The title of the summary page
* `baseUrl`: The base URL used to clone the repositories
* `example`: Should be one of the public repositories

Here is an example:

```
title: "my repositories"
baseUrl: "https://my.repo.com"
example: "pi-hoole"
```

If you add a file called `description` in the `.pijul` directory of your public
repositories, its content will be used by `pi-hoole-web` when it gives a summary
of the public repositories.

## Limitations

### Private Branches

The command `pijul patch` does not have an argument to specify the branch from
which a patch is initially fetched; as a consequence, having read access to a
repo, even for another branch where the patch is not applied, is enough.  For
this reason, if a user who obtains a hash for a patch of a branch they cannot
access can fetch the patch. That is, a patch is as private as its hash. Private
branches will eventually be supported in a better manner, but for now, private
branches should mean separated repositories.