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.0.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.0-py3-none-any.whl (12.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: zammad_pgp_import-0.3.0.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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.0.tar.gz
Algorithm Hash digest
SHA256 71ebed09617cb3654bdd8064d63d0b882fbdc37b7910944ff65fb8728d45971e
MD5 9ec35fe33e69b38f2eaa1738797f84f4
BLAKE2b-256 b8b974f8810292fa949ea87372bf87b69c5ef8ede65c4c4edfbd44f1b3ba46d0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: zammad_pgp_import-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 12.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8aac7359d5043ce26ce88574b7b9fbd42e6d4322c112a96c42c52154c26ff647
MD5 26e5bd837a21c0a2bc55c146824b65f2
BLAKE2b-256 71919a1ce2afbcedcbee78985149ebc29f169dee2d915492920633d119ce8319

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