PyKMIP - Key Management Interoperability Protocol
PyKMIP (Python Key Management Interoperability Protocol) is a client library for interacting with KMIP servers, enabling operations such as creating, retrieving, deleting, and managing cryptographic keys and objects. The current version is 0.10.0, and it follows a somewhat irregular but active release cadence, typically with bug fixes and minor features between major functional updates.
Common errors
-
ModuleNotFoundError: No module named 'pykmip.pie'
cause Incorrect import path; the core components of PyKMIP are under the `kmip.pie` namespace.fixChange your import statements from `from pykmip...` to `from kmip.pie...`. For example, `from kmip.pie.client import KmipClient`. -
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:1129)
cause The client failed to verify the server's TLS certificate, or the client's own certificate/key is invalid/missing. Common reasons include missing CA certificate (`ca` parameter), incorrect certificate chain, expired certificates, or hostname mismatch.fixEnsure the `ca` parameter points to the correct CA certificate chain file that signed the server's certificate. Verify `cert` and `key` parameters for the client are valid. Check certificate expiry dates and confirm the server's hostname matches its certificate's common name (CN) or Subject Alternative Name (SAN). -
ConnectionRefusedError: [Errno 111] Connection refused
cause The KMIP server is not running, is not listening on the specified host/port, or a firewall is blocking the connection.fixVerify the KMIP server process is active. Check the server's configuration for the listening IP address and port. Use `ping`, `telnet`, or `nc` to test network connectivity to the KMIP host and port (e.g., `telnet localhost 5696`). Disable firewalls temporarily for testing, if applicable. -
AttributeError: 'NoneType' object has no attribute 'uuid'
cause A KMIP operation (e.g., `create`, `get`) returned a `None` result because the operation failed, but the code attempted to access attributes like `uuid` or `managed_object` directly without checking the `result_status`.fixAlways check `result.result_status == enums.ResultStatus.SUCCESS` before attempting to access attributes of the result object. Handle non-success statuses gracefully, often by logging `result.result_reason` and `result.result_status`.
Warnings
- breaking Major internal refactoring of the `KmipClient` and TLS context management in v0.8.0. Direct access to internal methods like `_build_tls_context` will break.
- gotcha PyKMIP's package structure uses the `kmip.pie` namespace for its core components (client, enums, objects), not `pykmip` directly. This is a common source of `ModuleNotFoundError`.
- gotcha TLS configuration is critical and often misconfigured. Incorrect certificate paths, formats, or hostname mismatches can lead to `SSLError` or `ConnectionRefusedError`.
- gotcha Explicitly setting `ssl_version` (e.g., `PROTOCOL_TLSv1_2`) can limit compatibility. While common in PyKMIP examples, Python's `ssl` module generally recommends `PROTOCOL_TLS` for negotiation.
Install
-
pip install pykmip
Imports
- KmipClient
from pykmip.client import KmipClient
from kmip.pie.client import KmipClient
- enums
from pykmip import enums
from kmip.pie import enums
- objects
from pykmip import objects
from kmip.pie import objects
Quickstart
import os
from kmip.pie.client import KmipClient
from kmip.pie import enums, objects
# Configure KMIP server details from environment variables for security
KMIP_HOST = os.environ.get("KMIP_HOST", "localhost")
KMIP_PORT = int(os.environ.get("KMIP_PORT", "5696"))
CLIENT_CERT_PATH = os.environ.get("CLIENT_CERT_PATH", "./client.pem")
CLIENT_KEY_PATH = os.environ.get("CLIENT_KEY_PATH", "./client.key")
CA_CERT_PATH = os.environ.get("CA_CERT_PATH", "./ca.pem")
try:
# Initialize the KMIP client with TLS configuration
with KmipClient(
host=KMIP_HOST,
port=KMIP_PORT,
cert=CLIENT_CERT_PATH,
key=CLIENT_KEY_PATH,
ca=CA_CERT_PATH,
ssl_version="PROTOCOL_TLSv1_2" # Explicit TLSv1.2, or let system negotiate (PROTOCOL_TLS)
) as client:
client.open()
print(f"Successfully connected to KMIP server at {KMIP_HOST}:{KMIP_PORT}")
# Example 1: Create a new symmetric key
print("\nCreating a 256-bit AES symmetric key...")
create_result = client.create(
enums.ObjectType.SYMMETRIC_KEY,
enums.CryptographicAlgorithm.AES,
256,
enums.CryptographicUsageMask.ENCRYPT
)
if create_result.result_status == enums.ResultStatus.SUCCESS:
key_uuid = create_result.uuid
print(f"Key created successfully. UUID: {key_uuid}")
# Example 2: Destroy the created key
print(f"\nDestroying key with UUID: {key_uuid}...")
destroy_result = client.destroy(key_uuid)
if destroy_result.result_status == enums.ResultStatus.SUCCESS:
print(f"Key {key_uuid} destroyed successfully.")
else:
print(f"Failed to destroy key: {destroy_result.result_reason.name}")
else:
print(f"Failed to create key: {create_result.result_reason.name} ({create_result.result_status.name})")
except ConnectionRefusedError:
print(f"Error: Connection refused. Is the KMIP server running on {KMIP_HOST}:{KMIP_PORT}?")
except FileNotFoundError as e:
print(f"Error: Certificate or key file not found: {e}. Check paths: {CLIENT_CERT_PATH}, {CLIENT_KEY_PATH}, {CA_CERT_PATH}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# The 'with' statement handles client closing automatically
print("\nKMIP client operations completed.")