Identities API¶
The identities module manages client certificates for authenticated Gemini sites.
Overview¶
Some Gemini sites require client certificates for authentication. Astronomo can:
- Generate new self-signed certificates
- Store certificates persistently
- Associate certificates with specific hosts
- Present certificates when requested
Certificates are stored in ~/.config/astronomo/identities/.
API Reference¶
identities
¶
Client certificate identity management for Astronomo.
This module provides identity storage for Gemini client certificates with TOML persistence and URL prefix matching.
Identity
dataclass
¶
Identity(
id: str,
name: str,
fingerprint: str,
cert_path: Path,
key_path: Path,
url_prefixes: list[str] = list(),
created_at: datetime = datetime.now(),
expires_at: datetime | None = None,
)
Represents a client certificate identity.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
Unique identifier (UUID) |
name |
str
|
Human-readable name for the identity |
fingerprint |
str
|
SHA-256 fingerprint of the certificate |
cert_path |
Path
|
Path to the certificate PEM file |
key_path |
Path
|
Path to the private key PEM file |
url_prefixes |
list[str]
|
List of URL prefixes this identity is used for |
created_at |
datetime
|
When the identity was created |
expires_at |
datetime | None
|
Certificate expiration date |
add_url_prefix
¶
create
classmethod
¶
create(
name: str,
fingerprint: str,
cert_path: Path,
key_path: Path,
expires_at: datetime | None = None,
) -> Self
Create a new identity with auto-generated ID.
Source code in src/astronomo/identities.py
from_dict
classmethod
¶
Create from dictionary (TOML deserialization).
Source code in src/astronomo/identities.py
matches_url
¶
remove_url_prefix
¶
Remove a URL prefix. Returns True if removed.
to_dict
¶
Convert to dictionary for TOML serialization.
Source code in src/astronomo/identities.py
IdentityManager
¶
Manages client certificate identities with TOML persistence.
Provides CRUD operations for identities, certificate generation, and URL prefix matching.
Storage locations
- Metadata: ~/.config/astronomo/identities.toml
- Certificates: ~/.config/astronomo/certificates/{id}.pem
- Keys: ~/.config/astronomo/certificates/{id}.key
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config_dir
|
Path | None
|
Directory for storing identity files. Defaults to ~/.config/astronomo/ |
None
|
Source code in src/astronomo/identities.py
add_url_prefix
¶
Associate a URL prefix with an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity |
required |
url_prefix
|
str
|
URL prefix to associate (e.g., "gemini://example.com/") |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if successful, False if identity not found |
Source code in src/astronomo/identities.py
create_identity
¶
create_identity(
name: str,
hostname: str,
key_size: int = 2048,
valid_days: int = 365,
) -> Identity
Generate a new identity with self-signed certificate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable name for the identity |
required |
hostname
|
str
|
Hostname for the certificate (used in CN/SAN) |
required |
key_size
|
int
|
RSA key size in bits (default: 2048) |
2048
|
valid_days
|
int
|
Certificate validity period in days (default: 365) |
365
|
Returns:
| Type | Description |
|---|---|
Identity
|
The created Identity |
Source code in src/astronomo/identities.py
discover_lagrange_identities
¶
Discover .crt/.key pairs in a Lagrange idents directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
idents_path
|
Path
|
Path to Lagrange idents directory |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[str, Path, Path]]
|
List of (name, cert_path, key_path) tuples for valid pairs |
Source code in src/astronomo/identities.py
get_all_identities
¶
get_all_identities_for_url
¶
Find all identities that have URL prefixes matching the given URL.
Unlike get_identity_for_url() which returns only the longest-prefix match, this returns ALL identities that could be used for the URL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The URL to match against |
required |
Returns:
| Type | Description |
|---|---|
list[Identity]
|
List of matching Identity objects, sorted by longest prefix first |
Source code in src/astronomo/identities.py
get_identity
¶
get_identity_for_url
¶
Find the identity that matches a URL based on prefixes.
Uses longest-prefix matching: if multiple identities match, the one with the longest matching prefix is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The URL to match against |
required |
Returns:
| Type | Description |
|---|---|
Identity | None
|
The matching Identity, or None if no match |
Source code in src/astronomo/identities.py
has_identity_with_fingerprint
¶
Check if an identity with the given fingerprint already exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fingerprint
|
str
|
SHA-256 fingerprint to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if an identity with this fingerprint exists |
Source code in src/astronomo/identities.py
import_from_lagrange
¶
import_from_lagrange(
idents_path: Path | None = None,
names: dict[Path, str] | None = None,
) -> LagrangeImportResult
Import identities from Lagrange browser.
Discovers .crt/.key pairs in the Lagrange idents directory, validates certificates, and imports them into Astronomo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
idents_path
|
Path | None
|
Optional explicit path to idents directory. If None, auto-detects based on OS. |
None
|
names
|
dict[Path, str] | None
|
Optional dict mapping cert_path to identity name. If provided, uses these names instead of filenames. |
None
|
Returns:
| Type | Description |
|---|---|
LagrangeImportResult
|
LagrangeImportResult with import statistics |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If Lagrange idents directory not found |
Source code in src/astronomo/identities.py
import_identity_from_custom_files
¶
import_identity_from_custom_files(
name: str, cert_path: Path, key_path: Path | None = None
) -> Identity
Import an identity from custom certificate and key files.
Supports both separate cert/key files and combined PEM files containing both certificate and private key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable name for the identity |
required |
cert_path
|
Path
|
Path to certificate PEM file (may also contain key) |
required |
key_path
|
Path | None
|
Path to private key PEM file. If None, assumes cert_path contains both certificate and key (combined PEM). |
None
|
Returns:
| Type | Description |
|---|---|
Identity
|
The imported Identity |
Raises:
| Type | Description |
|---|---|
ValueError
|
If certificate is invalid, expired, or files are missing |
FileNotFoundError
|
If source files don't exist |
Source code in src/astronomo/identities.py
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | |
import_identity_from_files
¶
Import an identity from existing certificate and key files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable name for the identity |
required |
source_cert_path
|
Path
|
Path to source certificate PEM file |
required |
source_key_path
|
Path
|
Path to source private key PEM file |
required |
Returns:
| Type | Description |
|---|---|
Identity
|
The imported Identity |
Raises:
| Type | Description |
|---|---|
ValueError
|
If certificate is invalid or expired |
FileNotFoundError
|
If source files don't exist |
Source code in src/astronomo/identities.py
is_identity_valid
¶
Check if identity's certificate exists and is not expired.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if certificate exists and is valid, False otherwise |
Source code in src/astronomo/identities.py
regenerate_certificate
¶
regenerate_certificate(
identity_id: str,
hostname: str,
key_size: int = 2048,
valid_days: int = 365,
) -> bool
Regenerate certificate for existing identity.
Note: This creates a new key pair and fingerprint. The server will see this as a new identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity to regenerate |
required |
hostname
|
str
|
Hostname for the new certificate |
required |
key_size
|
int
|
RSA key size in bits |
2048
|
valid_days
|
int
|
Certificate validity period in days |
365
|
Returns:
| Type | Description |
|---|---|
bool
|
True if successful, False if identity not found |
Source code in src/astronomo/identities.py
remove_identity
¶
Remove an identity and its certificate files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if identity was found and removed, False otherwise |
Source code in src/astronomo/identities.py
remove_url_prefix
¶
Remove a URL prefix from an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity |
required |
url_prefix
|
str
|
URL prefix to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if successful, False if identity or prefix not found |
Source code in src/astronomo/identities.py
rename_identity
¶
Rename an identity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identity_id
|
str
|
ID of the identity to rename |
required |
new_name
|
str
|
New name for the identity |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if identity was found and renamed, False otherwise |
Source code in src/astronomo/identities.py
Example Usage¶
from astronomo.identities import IdentityManager, Identity
# Load identity manager
manager = IdentityManager()
# Create a new identity (generates certificate)
identity = manager.create_identity(
name="My Identity",
common_name="user@example.com",
)
# Associate identity with a host
manager.set_identity_for_host("example.com", identity.id)
# Get identity for a host
identity = manager.get_identity_for_host("example.com")
if identity:
print(f"Using identity: {identity.name}")
print(f"Certificate: {identity.cert_path}")
print(f"Key: {identity.key_path}")
# List all identities
for identity in manager.list_identities():
print(f"- {identity.name}")
Certificate Storage¶
Each identity is stored as: