tiny_ca.db package¶
- class tiny_ca.db.BaseDB[source]¶
Bases:
ABCAbstract contract for the certificate registry database adapter.
Defines all operations that the application layer requires from the persistence tier. Concrete implementations (e.g.
SyncDBHandler) provide the actual SQL queries and transaction management.All methods that return a
CertificateRecordmust returnNone(not raise an exception) when the requested record simply does not exist. Exceptions are reserved for genuine infrastructure failures (connection errors, constraint violations, etc.).- abstractmethod delete_by_uuid(uuid)[source]¶
Permanently delete the certificate record identified by uuid.
This is a hard delete — the row is removed from the database. The caller is responsible for also removing the corresponding filesystem artefacts via
BaseStorage.delete_certificate_folder.
- abstractmethod get_by_name(common_name)[source]¶
Retrieve the currently active certificate record for a given Common Name.
Implementations must filter to only
VALIDrecords so that the caller always receives the live certificate orNone— never a revoked or expired one.- Parameters:
common_name (str) – The CN (Common Name) field from the certificate Subject to look up.
- Returns:
The active VALID record for common_name, or
Noneif no such record exists.- Return type:
CertificateRecord | None
- abstractmethod get_by_serial(serial)[source]¶
Retrieve a certificate record by its X.509 serial number.
- Parameters:
serial (int) – Integer serial number to look up. Implementations are responsible for any type conversion required by the underlying storage format (e.g. converting to
strfor string-typed database columns).- Returns:
The matching record regardless of its current status (VALID, REVOKED, EXPIRED), or
Noneif no record exists for serial.- Return type:
CertificateRecord | None
- abstractmethod get_expiring(within_days=30)[source]¶
Return VALID certificates that expire within within_days calendar days.
Only records with
status == VALIDare considered — already-revoked or expired records are excluded.- Parameters:
within_days (int) – Look-ahead window in calendar days. Default:
30.- Returns:
Records ordered by
not_valid_afterascending (soonest first). Returns an empty list on error.- Return type:
- abstractmethod get_revoked_certificates()[source]¶
Yield certificate records that should appear in the current CRL.
Implementations define their own freshness window (e.g. only records revoked within the past 365 days and not yet expired), but must yield objects that expose at minimum:
serial_number— castable tointrevocation_date— adatetimeobjectrevocation_reason— an integer RFC 5280 reason code
- Yields:
CertificateRecord – Records (or row-like objects) for each revoked certificate that falls within the implementation’s CRL inclusion window.
- Return type:
- abstractmethod list_all(status=None, key_type=None, limit=100, offset=0)[source]¶
Return a paginated list of certificate records with optional filters.
- Parameters:
status (str | None) – Filter by lifecycle state (
"valid","revoked","expired").Nonereturns all statuses.key_type (str | None) – Filter by certificate category (
"ca","service","device", etc.).Nonereturns all types.limit (int) – Maximum number of records to return. Default:
100.offset (int) – Number of records to skip (for pagination). Default:
0.
- Returns:
Matching records ordered by
iddescending (newest first). Returns an empty list on error.- Return type:
- abstractmethod register_cert_in_db(cert, uuid, key_type=CertType.DEVICE)[source]¶
Persist a newly issued certificate to the registry.
Creates a new record with
status=VALIDpopulated from the certificate metadata. The implementation must extract the CN fromcert.subjectand store the full PEM encoding for later retrieval.- Parameters:
cert (x509.Certificate) – The issued X.509 certificate object to register.
uuid (str) – UUID that identifies the filesystem folder containing the corresponding
.pem,.key, and.csrartefact files.key_type (CertType) – Certificate category (CA, USER, SERVICE, DEVICE, INTERNAL). Default:
CertType.DEVICE.
- Returns:
Trueif the record was persisted successfully;Falseif the operation failed (the implementation must log the reason and roll back any partial changes).- Return type:
- abstractmethod revoke_certificate(serial_number, reason=<ReasonFlags.unspecified: 'unspecified'>)[source]¶
Mark a certificate as revoked and record the reason and timestamp.
Implementations must: 1. Look up the record by serial_number filtered to
status=VALID. 2. If not found, return(False, <NOT_FOUND status>)without error. 3. Updatestatus,revocation_reason, andrevocation_date. 4. Commit atomically; roll back on any exception.- Parameters:
serial_number (int) – Serial number of the certificate to revoke.
reason (x509.ReasonFlags) – RFC 5280 §5.3.1 revocation reason code. Default:
x509.ReasonFlags.unspecified(code 0).
- Returns:
(success, status_value)where status_value is implementation- defined (typically aRevokeStatusenum member).Trueindicates the revocation was committed;Falsemeans it was not (reason encoded in status_value).- Return type:
- abstractmethod update_status_expired()[source]¶
Bulk-update all VALID certificates whose
not_valid_afterhas passed.Sets
status = "expired"for every record where: -status == "valid"-not_valid_after < now (UTC)This method is intended to be called periodically by a background task (e.g. a cron job or an APScheduler job) so that status queries reflect reality without per-request date comparisons.
- Returns:
Number of rows updated. Returns
0on error (after logging).- Return type:
- class tiny_ca.db.CertificateRecord(**kwargs)[source]¶
Bases:
BaseORM model for a single certificate entry in the registry.
Maps to the
certificatestable. Each row represents one certificate that has been issued by the CA, regardless of its current lifecycle state.Columns¶
- idint
Auto-incremented surrogate primary key. Not exposed to application code; use
serial_numberas the business key.- serial_numberstr
X.509 serial number stored as a decimal string. Unique and indexed. String storage avoids integer overflow for 160-bit serials (RFC 5280).
- common_namestr
Common Name (CN) extracted from the certificate Subject at issuance time. Not unique; the same CN may appear across different certificate generations (e.g. after rotation).
- statusstr
Current lifecycle state. One of the
CertificateStatusvalues:"valid","revoked","expired", or"unknown". Defaults toCertificateStatus.VALIDon insertion.- not_valid_beforedatetime
Start of the certificate’s validity period (UTC, naive datetime as stored by SQLAlchemy’s
DateTimeColumn type).- not_valid_afterdatetime
End of the certificate’s validity period (UTC, naive datetime). Indexed to allow efficient queries for expired certificates.
- key_typestr
Certificate category stored as the
CertTypeenum’s string value (e.g."ca","device","service"). Defaults toCertType.DEVICE.value.- certificate_pemstr
Full PEM-encoded public certificate. Allows reconstruction of the
x509.Certificateobject without accessing the filesystem.- revocation_datedatetime | None
UTC timestamp at which the certificate was revoked.
Nonefor non-revoked certificates.- revocation_reasonint | None
RFC 5280 §5.3.1 revocation reason code stored as an integer.
Nonefor non-revoked certificates. Maps to the integer value of the correspondingx509.ReasonFlagsmember.- uuidstr | None
UUID string that identifies the filesystem folder (managed by
BaseStorage) holding the.pem,.key, and.csrfiles for this certificate.Noneif no filesystem artefacts exist.
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- __init__(**kwargs)¶
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- class tiny_ca.db.CertificateStatus(value)[source]¶
Bases:
StrEnumLifecycle state of a certificate record in the registry.
Stored as a lowercase string in the
statuscolumn ofCertificateRecordso the value is human-readable in raw SQL output.Members¶
- VALID :
The certificate was issued successfully and has not been revoked or expired. Active certificates used for authentication or encryption are expected to be in this state.
- REVOKED :
The certificate was explicitly revoked before its natural expiry. The
revocation_dateandrevocation_reasoncolumns on the correspondingCertificateRecordrow must be non-null.- EXPIRED :
The certificate’s
not_valid_afterdate has passed. This status may be set by a background job; alternatively, callers can detect expiry by comparingnot_valid_afterto the current time.- UNKNOWN :
The status could not be determined, typically because no record was found for the requested serial number. Used as a safe sentinel value by
CertLifecycleManager.get_certificate_status.
- EXPIRED = 'expired'¶
- REVOKED = 'revoked'¶
- UNKNOWN = 'unknown'¶
- VALID = 'valid'¶
- class tiny_ca.db.RevokeStatus(value)[source]¶
Bases:
EnumEnumerated outcomes for a certificate revocation attempt.
Used as the second element of the
(bool, RevokeStatus)tuple returned byBaseDB.revoke_certificateimplementations. The boolean indicates overall success; this enum provides the machine-readable reason when the operation did not succeed, and a confirmation token when it did.Members¶
- NOT_FOUND :
No active (
VALID) certificate with the requested serial number exists in the registry. The certificate may already be revoked, expired, or was never registered.- UNKNOWN_ERROR :
An unexpected internal error (e.g. database constraint violation, connection failure) prevented the revocation. The implementation must log the underlying exception before returning this status.
- OK :
The revocation was committed successfully. The certificate record has been updated with
status=REVOKED, arevocation_date, and the providedrevocation_reason.
Examples
>>> success, status = db.revoke_certificate(serial=12345, reason=ReasonFlags.key_compromise) >>> if not success: ... if status == RevokeStatus.NOT_FOUND: ... logger.warning("Certificate not found") ... else: ... logger.error("Internal revocation error")
- NOT_FOUND = 'The certificate was not revoked because there is no valid certificate with the specified serial number.'¶
- OK = 'success'¶
- UNKNOWN_ERROR = 'The certificate was not revoked due to an internal error. Please review the service logs.'¶
- class tiny_ca.db.SyncDBHandler(db_url, logger=None)[source]¶
Bases:
BaseDBSynchronous, SQLAlchemy-backed certificate registry.
Implements the full
BaseDBcontract with explicit, atomic transaction management. Every public method follows the same pattern:Open a new session via
self._db.session().Execute the query / mutation inside a
tryblock.Commit on success or roll back on any exception.
Always close the session in the
finallyblock.
This guarantees that no session is leaked regardless of outcome, and that partial writes are never visible to other readers.
- Parameters:
db_url (str) – SQLAlchemy database URL forwarded to
DatabaseManager.logger (Logger | None) – Logger for operational and diagnostic messages. Falls back to
DEFAULT_LOGGERwhenNone.
- get_by_name(common_name)[source]¶
Fetch the active VALID certificate record for the given Common Name.
Only records with
status == CertificateStatus.VALIDare returned. Revoked and expired records are ignored so that the caller always receives the currently-active certificate for a given CN, orNoneif no active certificate exists.- Parameters:
common_name (str) – The CN (Common Name) value from the certificate Subject field.
- Returns:
The matching VALID record, or
Noneif absent or on DB error.- Return type:
CertificateRecord | None
- get_by_serial(serial)[source]¶
Fetch a single certificate record by its X.509 serial number.
The serial is stored as a string in the database (to avoid integer overflow across all backends); the conversion is handled internally.
- Parameters:
serial (int) – Integer serial number to look up.
- Returns:
The matching ORM record, or
Noneif no record exists for serial or if a database error occurs.- Return type:
CertificateRecord | None
- get_expiring(within_days=30)[source]¶
Return VALID certificates expiring within within_days calendar days.
- Parameters:
within_days (int) – Look-ahead window in days. Default:
30.- Returns:
Records ordered by
not_valid_afterascending. Empty list on error.- Return type:
- get_revoked_certificates()[source]¶
Yield revoked certificate rows relevant for the current CRL window.
A record is included when all of the following conditions hold:
revocation_dateis notNULL— the certificate was actually revoked.not_valid_after > now— the certificate has not yet expired; expired certificates need not appear in a CRL because relying parties will reject them regardless.revocation_date > now - 365 days— the revocation is recent enough to be relevant. This prevents unbounded CRL growth from very old entries that no relying party could still encounter.
Only three columns are selected (
serial_number,revocation_date,revocation_reason) to minimise data transfer; callers must not access otherCertificateRecordattributes on the yielded rows.- Yields:
CertificateRecord – SQLAlchemy
Rowobjects withserial_number,revocation_date, andrevocation_reasonattributes.- Return type:
Generator[CertificateRecord, None, None]
Notes
All rows are fetched in a single query before yielding begins. The session is closed in the
finallyblock; do not use the yielded rows after the generator has been exhausted or abandoned.- Return type:
- list_all(status=None, key_type=None, limit=100, offset=0)[source]¶
Return a paginated list of certificate records with optional filters.
- Parameters:
- Returns:
Records ordered by
iddescending. Empty list on error.- Return type:
- register_cert_in_db(cert, uuid, key_type=CertType.DEVICE)[source]¶
Persist a newly issued certificate to the registry.
Creates a new
CertificateRecordrow withstatus=VALIDfrom the metadata and PEM encoding of cert. The full PEM is stored so the certificate can be reconstructed independently of the filesystem.- Parameters:
cert (x509.Certificate) – The issued X.509 certificate. Its Subject must contain at least one
commonName(CN) attribute.uuid (str) – UUID string that identifies the storage folder holding the corresponding
.pem,.key, and.csrfiles.key_type (CertType) – Certificate category. Stored as its
strvalue (e.g."device"). Default:CertType.DEVICE.
- Returns:
Trueif the record was committed successfully;Falseif the operation was rolled back due to an error (e.g. duplicate serial, constraint violation).- Return type:
- Raises:
IndexError – Re-raised if the certificate contains no CN attribute, indicating a malformed certificate that should not be stored.
- revoke_certificate(serial_number, reason=<ReasonFlags.unspecified: 'unspecified'>)[source]¶
Mark a certificate as revoked and record the reason and timestamp.
Looks up the certificate by serial_number filtered to
status == VALID— already-revoked or unknown serials are treated as not found. On success the record is updated in-place: -status→CertificateStatus.REVOKED-revocation_reason→ integer value of reason -revocation_date→ current UTC timestampThe change is committed atomically; a rollback is performed on any unexpected error.
- Parameters:
serial_number (int) – Serial number of the certificate to revoke.
reason (x509.ReasonFlags) – RFC 5280 §5.3.1 revocation reason code. Default:
x509.ReasonFlags.unspecified(code 0).
- Returns:
(True, RevokeStatus.OK)— revocation committed.(False, RevokeStatus.NOT_FOUND)— no VALID cert with that serial.(False, RevokeStatus.UNKNOWN_ERROR)— unexpected internal error.- Return type:
- tiny_ca.db.SyncDatabaseManager¶
alias of
DatabaseManager
Submodules¶
- tiny_ca.db.async_db_manager module
AsyncDBHandlerAsyncDBHandler.__init__()AsyncDBHandler.delete_by_uuid()AsyncDBHandler.get_by_name()AsyncDBHandler.get_by_serial()AsyncDBHandler.get_expiring()AsyncDBHandler.get_revoked_certificates()AsyncDBHandler.list_all()AsyncDBHandler.register_cert_in_db()AsyncDBHandler.revoke_certificate()AsyncDBHandler.update_status_expired()
DatabaseManager
- tiny_ca.db.base_db module
- tiny_ca.db.const module
- tiny_ca.db.models module
- Module-level contents
- Design notes
CertificateRecordCertificateRecord.__init__()CertificateRecord.certificate_pemCertificateRecord.common_nameCertificateRecord.idCertificateRecord.key_typeCertificateRecord.not_valid_afterCertificateRecord.not_valid_beforeCertificateRecord.revocation_dateCertificateRecord.revocation_reasonCertificateRecord.serial_numberCertificateRecord.statusCertificateRecord.uuid
- tiny_ca.db.sync_db_manager module
- Module-level contents
- SOLID notes
DatabaseManagerSyncDBHandlerSyncDBHandler.__init__()SyncDBHandler.delete_by_uuid()SyncDBHandler.get_by_name()SyncDBHandler.get_by_serial()SyncDBHandler.get_expiring()SyncDBHandler.get_revoked_certificates()SyncDBHandler.list_all()SyncDBHandler.register_cert_in_db()SyncDBHandler.revoke_certificate()SyncDBHandler.update_status_expired()