Skip to content

Commit

Permalink
feat: add Print formula
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-grande committed May 24, 2024
1 parent cbf61e6 commit b09ecdc
Show file tree
Hide file tree
Showing 20 changed files with 487 additions and 0 deletions.
114 changes: 114 additions & 0 deletions salt/sys-print/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# sys-print

Printer environment in Qubes OS.

## Table of Contents

* [Description](#description)
* [Security](#security)
* [Installation](#installation)
* [Access Control](#access-control)
* [Usage](#usage)
* [Add a printer](#add-a-printer)
* [Print](#print)
* [Credits](#credits)

## Description

Creates a print server named "sys-print" and a named disposable
"disp-sys-print" qube for sending files to your configured printer, which can
be done over the network or with IPP-over-USB.

## Security

The client does not have CUPS, does not need internet connection and does not
have USB devices connected.

Using CUPS in a dedicated qube reduces attack surface and has a better
usability as you only need to configure the printer in one qube and other
qubes will have access through Qrexec.

If the devices connected to the server qube can attack the CUPS server, it can
escalate the attack to the client qube. Usage of disposables servers does not
prevent this from happening, it just avoids persistent infection on the
server, where you could attribute different printers to different levels of
trust.

Sending files to the print server with `qvm-copy` is always safer than
allowing a direct connection from the qube that wants to print files to the
qube that has access to the printer.

## Installation

- Top:
```sh
sudo qubesctl top.enable sys-print
sudo qubesctl --targets=tpl-sys-print,sys-print state.apply
sudo qubesctl top.disable sys-print
sudo qubesctl state.apply sys-print.appmenus
```

- State:
<!-- pkg:begin:post-install -->
```sh
sudo qubesctl state.apply sys-print.create
sudo qubesctl --skip-dom0 --targets=tpl-sys-print state.apply sys-print.install
sudo qubesctl --skip-dom0 --targets=dvm-sys-print,sys-print state.apply sys-print.configure
sudo qubesctl state.apply sys-print.appmenus
```
<!-- pkg:end:post-install -->

If you want to install all printer drivers:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-sys-print state.apply sys-print.install-driver-all
```

On the client template:
```sh
sudo qubesctl --skip-dom0 --targets=tpl-QUBE -print state.apply sys-print.install-client
```

The client qube requires the split Print service to be enabled:
```sh
qvm-features QUBE service.print-setup 1
```

## Access Control

_Default policy_: `ask` `all` requests requesting to use the
`qusal.Print` RPC service.

`Asking` can spawn multiple requests depending on the client, usage of `allow`
is recommended for trusted clients.

Allow access to the specified printing agent based on the qube tag:
```qrexecpolicy
qusal.Print * @tag:print-client @default allow target=sys-print
```

Always recommended to end with an explicit deny rule:
```qrexecpolicy
qusal.Print * @anyvm @anyvm deny
```

## Usage

### Add a printer

You will configure your printer from `sys-print` or `disp-sys-print`, it can
connect over the network or USB. If you do not want to save printing
configuration, use `disp-sys-print`.

On `sys-print` or `disp-sys-print`, add your printer:
```sh
system-config-printer
```

### Print

On the client, select the file to print, open it with an editor, viewer or
browser and target the desired printer.

## Credits

- [Unman](https://github.com/unman/shaker/tree/main/sys-print)
8 changes: 8 additions & 0 deletions salt/sys-print/appmenus.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{#
SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

{% from 'utils/macros/sync-appmenus.sls' import sync_appmenus -%}
{{ sync_appmenus('tpl-' ~ sls_path) }}
10 changes: 10 additions & 0 deletions salt/sys-print/appmenus.top
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

base:
'dom0':
- match: nodegroup
- sys-print.appmenus
8 changes: 8 additions & 0 deletions salt/sys-print/clone.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

{% from 'utils/macros/clone-template.sls' import clone_template -%}
{{ clone_template('debian-minimal', sls_path) }}
10 changes: 10 additions & 0 deletions salt/sys-print/clone.top
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

base:
'dom0':
- match: nodegroup
- sys-print.clone
24 changes: 24 additions & 0 deletions salt/sys-print/configure.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{#
SPDX-FileCopyrightText: 2022 - 2023 unman <unman@thirdeyesecurity.org>
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

"{{ slsdotpath }}-bind-dirs":
file.managed:
- name: /rw/config/qubes-bind-dirs.d/50-sys-print.conf
- source: salt://{{ slsdotpath }}/files/server/qubes-bind-dirs.d/50-sys-print.conf
- mode: '0644'
- user: root
- group: root
- makedirs: True

"{{ slsdotpath }}-rpc":
file.managed:
- name: /etc/qubes-rpc/qusal.Print
- source: salt://{{ slsdotpath }}/files/server/rpc/qusal.Print
- mode: '0755'
- user: root
- group: root
- makedirs: True
9 changes: 9 additions & 0 deletions salt/sys-print/configure.top
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

base:
'dvm-sys-print,sys-print':
- sys-print.configure
127 changes: 127 additions & 0 deletions salt/sys-print/create.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{#
SPDX-FileCopyrightText: 2022 - 2023 unman <unman@thirdeyesecurity.org>
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

{%- from "qvm/template.jinja" import load -%}
include:
- .clone
{% load_yaml as defaults -%}
name: tpl-{{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
prefs:
- audiovm: ""
features:
- set:
- default-menu-items: "system-config-printer.desktop qubes-run-terminal.desktop qubes-open-file-manager.desktop qubes.start.desktop"
- menu-items: "system-config-printer.desktop qubes-run-terminal.desktop qubes-open-file-manager.desktop qubes.start.desktop"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: dvm-{{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: tpl-{{ slsdotpath }}
- label: red
prefs:
- template: tpl-{{ slsdotpath }}
- label: red
- netvm: "*default*"
- audiovm: ""
- vcpus: 1
- memory: 300
- maxmem: 400
- autostart: False
- template_for_dispvms: True
- include_in_backups: True
features:
- enable:
- servicevm
- service.cups
- appmenus-dispvm
- disable:
- service.cups-browsed
- service.tinyproxy
- service.tracker
- service.evolution-data-server
- set:
- menu-items: "system-config-printer.desktop qubes-run-terminal.desktop qubes-open-file-manager.desktop qubes.start.desktop"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: disp-{{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: dvm-{{ slsdotpath }}
- label: red
- class: DispVM
prefs:
- template: dvm-{{ slsdotpath }}
- label: red
- netvm: "*default*"
- audiovm: ""
- vcpus: 1
- memory: 300
- maxmem: 400
- autostart: False
- include_in_backups: True
features:
- enable:
- servicevm
- service.cups
- disable:
- service.cups-browsed
- service.tinyproxy
- service.tracker
- service.evolution-data-server
- set:
- menu-items: "system-config-printer.desktop qubes-run-terminal.desktop qubes-open-file-manager.desktop qubes.start.desktop"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: {{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: tpl-{{ slsdotpath }}
- label: red
prefs:
- template: tpl-{{ slsdotpath }}
- label: red
- netvm: "*default*"
- audiovm: ""
- vcpus: 1
- memory: 300
- maxmem: 400
- autostart: False
- include_in_backups: True
features:
- enable:
- servicevm
- service.cups
- disable:
- service.cups-browsed
- service.tinyproxy
- service.tracker
- service.evolution-data-server
- set:
- menu-items: "system-config-printer.desktop qubes-run-terminal.desktop qubes-open-file-manager.desktop qubes.start.desktop"
{%- endload %}
{{ load(defaults) }}
{% from 'utils/macros/policy.sls' import policy_set with context -%}
{{ policy_set(sls_path, '80') }}
10 changes: 10 additions & 0 deletions salt/sys-print/create.top
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

base:
'dom0':
- match: nodegroup
- sys-print.create
9 changes: 9 additions & 0 deletions salt/sys-print/files/admin/policy/default.policy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later

## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.
qusal.Print * @anyvm @default ask default_target=sys-print
qusal.Print * @anyvm @anyvm deny
## vim:ft=qrexecpolicy
23 changes: 23 additions & 0 deletions salt/sys-print/files/client/systemd/qubes-print-forwarder.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# SPDX-FileCopyrightText: 2023 unman <unman@thirdeyesecurity.org>
#
# SPDX-License-Identifier: AGPL-3.0-or-later

[Unit]
Description=Print over Qrexec
After=qubes-qrexec-agent.service
ConditionPathExists=/var/run/qubes-service/print-setup

[Service]
ExecStart=/usr/bin/socat TCP4-LISTEN:631,reuseaddr,fork,end-close EXEC:"qrexec-client-vm @default qusal.Print"
Restart=on-failure
RestartSec=3

# Hardening
ProtectSystem=full
PrivateTmp=true
SystemCallArchitectures=native
MemoryDenyWriteExecute=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2023 unman <unman@thirdeyesecurity.org>
#
# SPDX-License-Identifier: AGPL-3.0-or-later

binds+=('/etc/cups')

# vim: ft=bash
7 changes: 7 additions & 0 deletions salt/sys-print/files/server/rpc/qusal.Print
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2023 unman <unman@thirdeyesecurity.org>
#
# SPDX-License-Identifier: AGPL-3.0-or-later

set -eu
exec socat STDIO TCP:localhost:631
14 changes: 14 additions & 0 deletions salt/sys-print/init.top
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>

SPDX-License-Identifier: AGPL-3.0-or-later
#}

base:
'dom0':
- match: nodegroup
- sys-print.create
'tpl-sys-print':
- sys-print.install
'dvm-sys-print,sys-print':
- sys-print.configure
Loading

0 comments on commit b09ecdc

Please sign in to comment.