Skip to main content

No project description provided

Project description

Zammad PGP import - Webhook & cli tools

The what and why

Zammad helpdesk supports PGP encryption and it works quite nice. But the current workflow of importing PGP keys is a bit cumbersome. Also, agents need special admin privileges to import PGP keys. This project provides a webhook that automatically imports PGP keys when some checks are completed. You need to configure a Zammad webhook that sends a POST request to this webhook for each new incoming ticket. The webhook automatically imports PGP keys attached to the ticket or keys found on a keyserver.

There are also some cli tools to import PGP keys manually or import PGP keys from a Thunderbird profile.

How does it work?

  1. Zammad receives a new ticket
  2. Zammad sends a webhook (must be configured manually in Zammad)
  3. This projects contains the backend of the webhook. There are two supported scenarios where PGP keys are imported:
    • The email has a PGP key attached. If sender's email address matches with the one of the attached PGP key, the Zammad API is used to import the key
    • If the email is PGP-encrypted: Use a PGP keyserver to find a valid PGP key and import it.

Quickstart

pip install zammad-pgp-import

cat secrets.source
export DEBUG="1"
export ZAMMAD_BASE_URL="https://tickets.example.org"
export ZAMMAD_TOKEN="auth token"
export BASIC_AUTH_USER="test"
export BASIC_AUTH_PASSWORD="test"
export LISTEN_HOST="0.0.0.0"
export LISTEN_PORT="22000"

source secrets.source

zammad-pgp-import -h
usage: zammad-pgp-import [-h] [--backend] [--import-key IMPORT_KEY] [--import-thunderbird IMPORT_THUNDERBIRD] [--version]

Zammad webhook that automatically imports PGP keys. There is also a cli to import PGP keys manually. Configuration is done via environment variables. Docs can be found here: https://github.com/kmille/zammad-pgp-auto-import

options:
  -h, --help            show this help message and exit
  --backend, -b         run webhook backend
  --import-key, -i IMPORT_KEY
                        use key server to import pgp key by supplied email/key id
  --import-thunderbird, -t IMPORT_THUNDERBIRD
                        Needs a global-messages-db.sqlite file. Get all email addresses from global-messages-db.sqlite (part of a Thunderbird profile). Try to find a PGP key and import it to Zammad. As there is rate limiting, we sleep
                        for a long time after each attempt. So you may want to run this on a server
  --version             show version

Configuration

Configuration of this tool is done via environment variables.

name of environment variable meaning required
DEBUG set 1 to enable debug log no
ZAMMAD_BASE_URL url of zammad instance, like https://tickets.example.org yes
ZAMMAD_TOKEN auth token/api key with enough permissions (see below) yes
BASIC_AUTH_USER username for webhook and monitoring endpoint authentication yes
BASIC_AUTH_PASSWORD password for webhook and monitoring endpoint authentication yes
LISTEN_HOST defaults to "127.0.0.1" no
LISTEN_PORT defaults to 22000 no
KEY_SERVER default PGP key server, default is https://keys.openpgp.org no

Zammad Webhook configuration

  1. Define webhook

  1. Create trigger (triggers webhook for every new ticket)

To get an API key for a production environment, I recommend:

  1. Create a new Zammad user, only used for the API
  2. Create a new role for the webhook user
  3. The role needs permissions to read tickets for all groups (to download ticket attachments) and the integration permission (to import PGP keys)

How to use it as a dev?

It's written in python and uses uv to manage dependencies.

source secrets.txt (see above)
uv run zammad_pgp_import/__init__.py --help

How to use it with Docker

You can use the Github Docker image:

docker pull ghcr.io/kmille/zammad-pgp-import

Or the Dockerhub image:

docker pull kmille2/zammad-pgp-import

You can use this docker-compose.yml:

services:
   zammad-pgp-import:
    image: ghcr.io/kmille/zammad-pgp-import
    environment:
      DEBUG: "1"
      BASIC_AUTH_USER: "test"
      BASIC_AUTH_PASSWORD: "test"
      ZAMMAD_BASE_URL: "https://tickets.example.org"
      ZAMMAD_TOKEN: "token"
    security_opt:
      - no-new-privileges
    cap_drop:
      - ALL

Example output

  1. Run the webhook backend
kmille@spring:~/projects/zammad-pgp-import# uv run zammad-pgp-import --backend
[2025-08-14 17:56:01,279  INFO] Starting webhook backend on 0.0.0.0:22000 (version 0.1.1a5, debug=True)
[2025-08-14 17:56:01,281  INFO] Serving on http://0.0.0.0:22000

...

zammad-pgp-import-1  | [2025-08-04 12:08:46,377  INFO] Received a new Ticket: https://tickets.example.org/#ticket/zoom/133 (from=<redacted>, is_encrypted=False)
zammad-pgp-import-1  | [2025-08-04 12:08:46,377 DEBUG] This attachment is not a PGP key (Content-Type='')                                                                                                                                      
zammad-pgp-import-1  | [2025-08-04 12:08:46,377 DEBUG] No PGP key was attached to this email                                                                                                                                                   
zammad-pgp-import-1  | [2025-08-04 12:08:46,377  INFO] Ticket does not have a PGP key attached. It is also not encrypted and/or PGP key was not found on a keysever                  

zammad-pgp-import-1  | [2025-08-05 13:24:06,815  INFO] Received a new Ticket: https://tickets.example.org/#ticket/zoom/139 (from=<redacted>, is_encrypted=True)
zammad-pgp-import-1  | [2025-08-05 13:24:06,815  INFO] Seems like a PGP key is attached to this email
zammad-pgp-import-1  | [2025-08-05 13:24:06,816 DEBUG] Downloading ticket attachment using Zammad API
zammad-pgp-import-1  | [2025-08-05 13:24:06,972 DEBUG] Successfully downloaded email attachment
zammad-pgp-import-1  | [2025-08-05 13:24:06,987 DEBUG] Importing PGP key using Zammad API
zammad-pgp-import-1  | [2025-08-05 13:24:07,126  INFO] Successfully imported pgp key <redacted> for email <redacted>
  1. Import PGP key via cli
[2025-08-14 17:58:26,621  INFO] Found key: PGPKey (emails=jelle@vdwaa.nl,jelle@archlinux.org,jvanderwaa@redhat.com fingerprint=E499C79F53C96A54E572FEE1C06086337C50773E
[2025-08-14 17:58:26,621  INFO] Found key: PGPKey (emails=jelle@vdwaa.nl,jelle@archlinux.org,jvanderwaa@redhat.com fingerprint=E499C79F53C96A54E572FEE1C06086337C50773E
[2025-08-14 17:58:26,626 DEBUG] Importing PGP key using Zammad API
[2025-08-14 17:58:26,789  INFO] Successfully imported PGP key
kmille@spring:~/projects/zammad-pgp-import# uv run zammad-pgp-import -i jelle@archlinux.org
[2025-08-14 17:58:35,483  INFO] Found key: PGPKey (emails=jelle@vdwaa.nl,jelle@archlinux.org,jvanderwaa@redhat.com fingerprint=E499C79F53C96A54E572FEE1C06086337C50773E
[2025-08-14 17:58:35,488 DEBUG] Importing PGP key using Zammad API
[2025-08-14 17:58:35,598 ERROR] Could not import PGP key: Key was already imported. API response: Fingerprint There is already a PGP key with the same fingerprint.
  1. Import PGP keys from Thunderbird profile
kmille@spring:~/projects/zammad-pgp-import# uv run zammad_pgp_import/__init__.py -t ~/.config/Thunderbird-LG/.thunderbird/....default-release/global-messages-db.sqlite                                                        
[2025-08-14 17:59:34,866 DEBUG] Read email: <redacted@bla.com>
...
[2025-08-14 18:00:45,224  INFO] Checking mail 1/3460: <redacted @ ....>
[2025-08-14 18:00:45,272 DEBUG] API error message: No key found for email address < redacted>
[2025-08-14 18:00:45,273  INFO] Could not find a PGP key for < redacted > using keyserver https://keys.openpgp.org
...
[2025-08-04 10:27:53,933  INFO] Doing 6/3448: <redacted>
[2025-08-04 10:27:53,969  INFO] Found key: PGPKey <redacted>
[2025-08-04 10:27:53,970 DEBUG] Importing PGP key using Zammad API
[2025-08-04 10:27:54,144  INFO] Successfully imported PGP key

Monitoring

You can monitor the webhook:

curl https://webhook.example.org/status -u webhook
Enter host password for user 'webhook':
{"status":"ok"}

In case of at least one error, {"status":"failed"} is returned. Both responses use status code 200. The authentication credentials are the same like the ones for the webhook endpoint. In case of an error, check the logs and restart the webhook.

KNOWN ISSUES/TODOs

  • TODO: handle expired PGP keys (do not import them)
  • TODO: improve tests
  • Please check this Zammad PGP issue (was fixed, but it is not released yet I think): https://github.com/zammad/zammad/issues/5170
  • Right now, agents don't get PGP encrypted notifications, even if they have a PGP key imported for that email address

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zammad_pgp_import-0.3.3.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zammad_pgp_import-0.3.3-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

File details

Details for the file zammad_pgp_import-0.3.3.tar.gz.

File metadata

  • Download URL: zammad_pgp_import-0.3.3.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for zammad_pgp_import-0.3.3.tar.gz
Algorithm Hash digest
SHA256 5bdcb2d6106c5c944facf5d423dace831e39db2af5aff81800272a6e9ba73bd5
MD5 c39f1d66f53178034b3a5ad76599c72c
BLAKE2b-256 fe3b5b06066e16e79c0a231429bc85f82efe719aa9f0f27ec6291c768b65c21f

See more details on using hashes here.

File details

Details for the file zammad_pgp_import-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: zammad_pgp_import-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 12.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for zammad_pgp_import-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 fd17d942cb9c77bbf0d408e40ac2bad473649b1b7ca035857fbea014e7542c96
MD5 e90e44a392e97e80b63064e4d140ba36
BLAKE2b-256 18dfac7646f1c06e0783995802d458098fac95fb94c28a4dbdd07530c8e64f7b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page