Skip to content

v0.4.6

Choose a tag to compare

@oleksandr-nc oleksandr-nc released this 20 Oct 07:49
cf6b7df

HaRP 0.4.6 checks what AppAPI sends before it acts on it, adds rules for the host paths ExApps may bind mount, and keeps HaRP's shared key out of ExApp containers. Everything AppAPI sends by default keeps working on every supported Nextcloud version.

Upgrading

  • Check the bind mounts of your ExApps (shown in their deploy options) before you upgrade. AppAPI sends the stored mounts again on every ExApp update, after it has removed the old container, so a mount that HaRP now refuses leaves that ExApp without a container. Refused from this release on: /proc, /sys, /boot, the container runtimes' state and runtime directories (/var/lib/docker apart from its volume directory, /var/lib/containerd, /var/lib/containers apart from its volume directory, /run/docker.sock, /var/run/docker.sock, and the containerd, Podman and CRI-O directories under /run and /var/run), /etc/shadow, /etc/gshadow, /etc/sudoers, /etc/sudoers.d, /etc/ssh, and any mount that contains one of them, such as /, /var, /etc, /run or /var/run. To recover an ExApp, unregister it with occ app_api:app:unregister <appid> --force (its data is kept unless you add --rm-data) and register it again with its deploy options (its environment variables and corrected mounts), because unregistering deletes them. See the "Upgrading" notes under HP_EXAPP_BIND_MOUNTS_* and HP_SHARED_KEY in the README.
  • Mounts that only log a warning in this release: /dev, /root, paths below /run and /var/run (apart from the runtime directories above), the Docker and Podman volume directories, read-write mounts below /etc (a mount of /etc itself is refused) and of /usr, /bin, /sbin, /lib, /lib64 and /var/spool, and mount modes other than ro or rw (such as z or RO, which mount read-write as before). A later release will refuse them; HP_EXAPP_BIND_MOUNTS_ENFORCE_ALL=true refuses them now. HaRP's log names the mount, the ExApp container and how to keep the mount.
  • Docker network of a deploy daemon: HaRP no longer creates ExApp containers for a deploy daemon whose Docker network (--net) is empty or contains a blank, : or a control character (the daemon check still passes), and a refused update leaves the ExApp without a container. Set a valid network name first.
  • Docker Engine ports: a deploy daemon whose Docker Engine port (--harp_docker_socket_port) is outside 24000-24099 is refused; add the port to HP_DOCKER_ENGINE_PORTS first. AppAPI does not show the reason: deploys and updates fail with 403 Forbidden, the daemon check fails, and enabling or disabling an ExApp fails without details (a disable can even be reported as done while the container keeps running); Nextcloud's log and HaRP's log name the allowed ports. Such an update fails before the old container is removed, so the ExApp keeps running its previous version.
  • Your own /haproxy.cfg: copy the new http-request del-header lines of haproxy.cfg.template into the same backends of your file; in docker_engine_backend they must come before the first http-request allow line, otherwise HAProxy ignores them.
  • ExApps already deployed keep working. Docker ExApp containers created by earlier releases keep HaRP's shared key until AppAPI creates them again at the ExApp's next version update; containers created by this release get an FRP token instead. To replace the key sooner, unregister the ExApp with occ app_api:app:unregister <appid> --force and register it again with its deploy options. Only ExApps that connect through FRP get the key or the token; Kubernetes ExApps and ExApps with FRP disabled never get it.
  • Rolling back to an earlier release: Docker ExApps deployed by 0.4.6 cannot connect to it (Kubernetes ExApps are not affected), and within a few minutes their login attempts get their address banned. With host networking, or with published ports when Nextcloud or its reverse proxy runs on the Docker host, that is usually also the address Nextcloud uses, so HaRP then refuses Nextcloud as well. The README explains how to recover.
  • Host networking: HaRP's internal ports are on the host's loopback interface, where every process on the host can use them, including ExApps with host networking. Read the new note under "Using Host Networking" in the README; the bridge deployment keeps ExApps away from these ports.
  • Scripts or monitoring that call port 8200 directly need to send the shared key now, apart from /heartbeat.

Changes

Requests from AppAPI (#123)

  • ExApp names must start with a letter or digit. Names, instance ids and role suffixes may only contain [A-Za-z0-9_.-] and be at most 63 characters long. Create also refuses an empty or invalid network_mode, an unknown restart policy, mount paths that are relative or contain :, a .. segment or control characters, and, on Docker, negative or non-integer memory and nanoCPUs limits. Each refusal is a 400 that names the field or the rule, sent before HaRP creates anything, including the ExApp's data volume.
  • New settings for bind mounts of ExApp containers: HP_EXAPP_BIND_MOUNTS_DISABLED, HP_EXAPP_BIND_MOUNTS_ALLOWED, HP_EXAPP_BIND_MOUNTS_DENIED (with a default list of system paths) and HP_EXAPP_BIND_MOUNTS_ENFORCE_ALL.
  • New HP_DOCKER_ENGINE_PORTS (default 24000-24099) for the Docker Engine ports AppAPI may address.
  • A malformed value of a new setting stops HaRP at startup within seconds, with the reason in the log.

The shared key

  • harp-shared-key no longer reaches ExApps, and neither it nor AppAPI's Authorization header reaches the Docker Engine (#123).
  • ExApp containers get an FRP token derived from the shared key instead of the key itself. HaRP accepts the token only for the FRP login; HaRP's own FRP client and remote Docker Engines keep using the key (#126).
  • The agent's own port (127.0.0.1:8200) checks the shared key too, apart from /heartbeat and the FRP login hook (#128).
  • Credentials, cookies and ExApp secrets are masked in the log, also in start.sh's printout of the FRP client configuration (#123).

FRP and bans

  • FRP logins without a token are refused with 400 and count toward the IP ban instead of failing with 500; IPv6 FRP clients get a ban counter per address (#123).
  • A wrong shared key on a request from AppAPI to an ExApp behind a trusted proxy counts against the client address from X-Forwarded-For or X-Real-IP, not against the proxy (#123).

Kubernetes

  • /info gives up on an unreachable Kubernetes API server after 3 seconds instead of 60, and reports why in a new error field (#119).
  • The create payload accepts image_pull_policy, which AppAPI uses for a local registry mapping (#122).

Logging

  • A failed ExApp lookup on a request from AppAPI is logged as one warning with its reason. The request still waits up to 5 seconds for Nextcloud, but the log now says why, instead of nothing at first and a traceback later (#124, #125).

Documentation and tests

  • The README documents the Kubernetes backend and its RBAC requirements (#120), resolves HaRP per request and passes WebSockets in the NGINX examples (#121), and has new upgrade and host networking notes (#123, #125, #128).
  • Unit tests run inside the built image in CI (#123).

What's Changed

  • fix(k8s): fail fast in /info when the API server does not answer by @oleksandr-nc in #119
  • feat(k8s): accept image_pull_policy in the create payload by @oleksandr-nc in #122
  • docs: document the Kubernetes backend and its RBAC requirements by @oleksandr-nc in #120
  • docs: resolve HaRP per request and pass WebSockets in the nginx examples by @oleksandr-nc in #121
  • fix(dev): use kind container's gateway IP instead of NC's proxy IP by @kyteinsky in #98
  • feat(docker): stricter request validation and bind mount rules by @oleksandr-nc in #123
  • fix: log failed ExApp lookups once, with their reason by @oleksandr-nc in #124
  • fix: clearer lookup failure reasons, more tests and upgrade notes by @oleksandr-nc in #125
  • feat: give ExApp containers an FRP token instead of the shared key by @oleksandr-nc in #126
  • fix: check the shared key on the agent's own port by @oleksandr-nc in #128
  • chore: bump version to 0.4.6 by @oleksandr-nc in #130

Full Changelog: v0.4.5...v0.4.6