KIZARD (KMIP Wizard Lizard) is a learning tool for understanding how a KMIP (Key Management Interoperability Protocol) client integrates with Thales CipherTrust Manager acting as a KMIP server.
It is a web-based KMIP client built on top of PyKMIP that exposes common key-management operations through a REST API and a browser UI.
Status: the symmetric-key lifecycle is implemented end-to-end — locate, create, register (import), get, get-attributes, activate, rotate (rekey), revoke/deactivate, destroy, and encrypt/decrypt (AES/3DES/DES, CBC, PKCS5) — exposed over both the REST API and the UI. The whole KMIP connection is configured at runtime through the browser, so the app comes up before any CipherTrust details are known (
.envremains an optional way to pre-seed them). The UI walks through a guided, ordered setup:
- Reach the server — a pre-flight probe checks DNS, TCP, and the TLS handshake against the KMIP endpoint before any client material exists.
- Confirm the CA — review the CA that issued CipherTrust's certificate and approve it, supplying the full trust chain (Issuing CA + Root CA).
- Provide a client certificate — upload an existing mTLS identity, or generate a key + CSR in the browser (RSA 2048/4096 or ECDSA P-256) to be signed by your CA.
- Verify the connection — a live KMIP
Locateround-trip confirms the server accepts the client certificate and speaks KMIP end-to-end; the key pane unlocks only once this passes.The key pane names every object (auto-generating
Kizard-Key-…when none is given), flags objects a rotation has replaced, and greys out any action the key's current state would reject. Encrypt/Decrypt (AES/3DES/DES · CBC · PKCS5) runs client-side by default — KIZARD fetches the key with a KMIPGetand ciphers locally — or, with a checkbox, server-side via the KMIPEncrypt/Decryptoperations so the key never leaves CipherTrust. Each key uses a fixed IV, created once and reused for every operation.
┌──────────────┐ HTTPS/REST ┌──────────────────┐ KMIP/mTLS ┌──────────────────────┐
│ React (UI) │ ───────────────────> │ FastAPI backend │ ───────────────────> │ CipherTrust Manager │
│ frontend/ │ │ backend/ │ (PyKMIP client) │ (KMIP server) │
└──────────────┘ └──────────────────┘ └──────────────────────┘
- frontend/ — React single-page app (Vite). Calls the backend REST API.
- backend/ — Python FastAPI service that wraps PyKMIP's
ProxyKmipClientand exposes key operations as JSON endpoints. - KMIP server — CipherTrust Manager (or any KMIP 1.x/2.x server) reached over a mutually-authenticated TLS connection.
KIZARD/
├── backend/ FastAPI service wrapping PyKMIP
│ ├── app/
│ │ ├── main.py App entrypoint / FastAPI instance
│ │ ├── core/ Settings & configuration
│ │ ├── kmip/ PyKMIP client wrapper
│ │ ├── models/ Pydantic request/response schemas
│ │ └── api/routes/ REST endpoints (health, keys, ...)
│ ├── tests/
│ ├── requirements.txt
│ └── .env.example
├── frontend/ React (Vite) single-page app
│ └── src/
├── docs/ Architecture & design notes
├── LICENSE Apache License 2.0
└── README.md
- Python 3.10–3.13 (see Compatibility notes).
- Node.js 18+
- Network access to a KMIP server (e.g. CipherTrust Manager) and a client certificate / private key trusted by that server.
- Python 3.10–3.13 are supported. PyKMIP 0.10 calls the module-level
ssl.wrap_socket(), which was removed in Python 3.12, so on 3.12+ the TLS connection would otherwise raiseAttributeError: module 'ssl' has no attribute 'wrap_socket'. The backend reinstalls a faithfulSSLContext-basedssl.wrap_socket(seeapp/core/ssl_compat.py, applied on import of the KMIP client) — preserving mutual-TLS and CA verification — so no Python-version pin is needed. The shim is a no-op on 3.10/3.11, which still ship the original function. - Use KMIP 1.4 with CipherTrust Manager. PyKMIP 0.10 cannot parse
CipherTrust's KMIP 2.0 responses (the response header fails to decode), so set
KMIP_VERSION=1.4. Versions 1.0–1.4 all work; 2.0 does not. - CipherTrust client-cert mapping. The KMIP interface authenticates the client by certificate. The cert's identity (e.g. its CN) must map to a CipherTrust user, and that user needs auto-registration enabled — otherwise the server completes the TLS handshake but closes every KMIP request.
From a fresh clone, one script checks for the runtime dependencies (git, Python ≥ 3.10, Node.js ≥ 18, npm), installs any that are missing via the system package manager, and sets up the backend virtualenv and frontend packages:
scripts/install.sh # install deps, set up venv/node_modules, then start the app
# backend :8000, UI :5173 (safe to re-run)
scripts/install.sh --nostart # ...or install/set up without starting
scripts/stop.sh # stop the app (scripts/stop.sh --clean also removes venv/node_modules)
scripts/start.sh # start it again later
scripts/reset.sh # clear the KMIP config so the guided setup starts overOn the first run backend/.env is seeded from the template — edit it with your
KMIP host and TLS material (under backend/certs/), then scripts/start.sh to
connect to your KMIP server.
Supported package managers: apt, dnf, yum, zypper, pacman. To run the pieces by hand instead, follow the steps below.
cd backend
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux/Mac: source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then edit .env with your KMIP server details
uvicorn app.main:app --reloadThe API listens on port 8000, with interactive docs at /docs — e.g.
http://<kizard-host>:8000/docs, or http://localhost:8000/docs when you are
on the machine itself.
cd frontend
npm install
npm run devThe UI listens on port 5173 and proxies API calls to the backend. Reach it at
http://<kizard-host>:5173, where <kizard-host> is the machine you installed
KIZARD on — localhost only from that machine itself.
CipherTrust Manager exposes a KMIP interface (default port 5696) that requires
mutual TLS. To connect, you will need:
- The CipherTrust Manager KMIP interface hostname and port.
- A KMIP client certificate and its private key (or generate a CSR in the UI and have your CA sign it).
- The CA chain that signed the server certificate (Issuing CA + Root CA).
The recommended path is the guided flow in the browser. Open the UI and work through the setup steps — reach the server, confirm the CA, provide the client certificate, then verify — each of which is described inline. Nothing needs to be known ahead of time; the app starts with no configuration.
Alternatively, pre-seed any of these in backend/.env (see
backend/.env.example) so the app comes up already configured — useful for a
repeatable demo. Values set in the UI at runtime take precedence.
KIZARD remembers what the guided flow configured — the server target, the CA
approval, and the mTLS material — under backend/data/. To walk the four setup
steps again from scratch, clear that state. Two equivalent ways:
- In the browser — the Start over button below the setup steps
(
DELETE /api/connection). Takes effect immediately, no restart. - On the command line —
scripts/reset.sh, which also restarts the backend if it is running:
scripts/reset.sh # prompts, then clears and restarts the backend
scripts/reset.sh --yes # no prompt
scripts/reset.sh --all # also forget each key's fixed IV (old ciphertext
# stops decrypting; keys on the server are untouched)Either way all four steps go back to un-done and the flow restarts at "Reach the server". Keys already created on CipherTrust are untouched — they live on the server, not in KIZARD.
A reset deliberately ignores anything pre-seeded in backend/.env, so a student
never skips a step: the server target is left explicitly blank rather than
re-seeded from KMIP_HOST, and client material at KMIP_CERT_PATH &c. stops
counting as configured. Those certificate files are yours, so they are
disregarded rather than deleted — nothing under backend/certs/ is removed. The
marker that suppresses them lives at backend/data/certs/ignore-env-material and
is dropped automatically the moment you supply a certificate through the UI.
The install — virtualenv, node modules, backend/.env — is left alone. To
uninstall instead, use scripts/stop.sh --clean.
Licensed under the Apache License 2.0. PyKMIP is also distributed under the Apache License 2.0.