FiscGuy uses mutual TLS authentication with ZIMRA FDMS. The device must hold a valid certificate issued by ZIMRA to submit any signed request.
init_devicegenerates an RSA key pair and a Certificate Signing Request (CSR)- For initial onboarding, the CSR is sent to ZIMRA FDMS
registerDevice - ZIMRA returns a signed certificate
- The certificate and private key are stored in the
Certsmodel - Every request to FDMS uses the certificate for mutual TLS authentication
Certificates are stored in the Certs model:
from fiscguy.models import Certs
cert = Certs.objects.first()
print(cert.certificate) # PEM-encoded certificate
print(cert.certificate_key) # PEM-encoded private key
print(cert.csr) # Original CSR
print(cert.production) # True = production, False = testingAt runtime, ZIMRAClient writes the certificate and key to a temporary PEM file used by the requests session. The temp file is cleaned up when the client is closed.
Certificates expire. When they do, all signed requests will fail with BadCertificateSignature or an authentication error.
POST /fiscguy/issue-certificate/
Response on success:
{"message": "Certificate issued successfully"}from fiscguy.services.certs_service import CertificateService
from fiscguy.models import Device
device = Device.objects.first()
CertificateService(device).issue_certificate()| Exception | Cause |
|---|---|
CertificateError |
FDMS rejected the renewal request |
Exception |
Unexpected error during renewal |
FiscGuy supports two key algorithms as per ZIMRA spec section 12:
| Algorithm | Spec reference |
|---|---|
| RSA 2048 | Section 12.1.2 |
| ECC ECDSA secp256r1 (P-256) | Section 12.1.1 |
The cryptography library is used for all key generation and signing. pyOpenSSL is no longer used.
- The private key never leaves the device. Only the CSR is sent to ZIMRA.
- Do not commit
Certsdata to version control. - In production, consider encrypting
Certs.certificateandCerts.certificate_keyat rest using a library likecryptography.fernet. See the project roadmap for planned support. - The temporary PEM file is written to a
tempfile.mkdtemp()directory and deleted whenZIMRAClient.close()is called.
from fiscguy import get_status
status = get_status()
# Check for certificate-related errors in the response
print(status)If the certificate is expired or invalid, get_status() will raise StatusError with an authentication error from FDMS.