Google Cloud Private Certificate Authority API client library for certificate lifecycle management
—
Certificate Revocation List (CRL) management for publishing and maintaining lists of revoked certificates. Supports automatic CRL generation, custom update schedules, and distribution through Google Cloud Storage for PKI infrastructure maintenance.
Retrieves certificate revocation list details and lists CRLs for a specific certificate authority.
def get_certificate_revocation_list(
self,
request: Union[GetCertificateRevocationListRequest, dict] = None,
*,
name: str = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> CertificateRevocationList:
"""
Get a certificate revocation list by name.
Args:
request: The request object
name: CRL resource name
retry: Retry configuration
timeout: Request timeout in seconds
metadata: Additional metadata
Returns:
CertificateRevocationList: The requested CRL resource
"""
def list_certificate_revocation_lists(
self,
request: Union[ListCertificateRevocationListsRequest, dict] = None,
*,
parent: str = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> pagers.ListCertificateRevocationListsPager:
"""
List certificate revocation lists for a CA.
Args:
request: The request object
parent: CA resource name
retry: Retry configuration
timeout: Request timeout in seconds
metadata: Additional metadata
Returns:
pagers.ListCertificateRevocationListsPager: Paginated response of CRLs
"""Updates certificate revocation list configuration including update schedules and publishing options.
def update_certificate_revocation_list(
self,
request: Union[UpdateCertificateRevocationListRequest, dict] = None,
*,
certificate_revocation_list: CertificateRevocationList = None,
update_mask: field_mask_pb2.FieldMask = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> operation.Operation:
"""
Update a certificate revocation list.
Args:
request: The request object
certificate_revocation_list: CRL with updated fields
update_mask: Fields to update
retry: Retry configuration
timeout: Request timeout in seconds
metadata: Additional metadata
Returns:
operation.Operation: Long-running operation for CRL update
"""class GetCertificateRevocationListRequest:
"""Request to get a certificate revocation list."""
name: str # CRL resource name
class ListCertificateRevocationListsRequest:
"""Request to list certificate revocation lists."""
parent: str # CA resource name
page_size: int # Maximum results per page
page_token: str # Pagination token
filter: str # Filter expression
order_by: str # Sort order
class UpdateCertificateRevocationListRequest:
"""Request to update a certificate revocation list."""
certificate_revocation_list: CertificateRevocationList # CRL with updates
update_mask: field_mask_pb2.FieldMask # Fields to update
request_id: str # Idempotency tokenclass CertificateRevocationList:
"""A Certificate Revocation List for a Certificate Authority."""
name: str # Resource name
sequence_number: int # CRL sequence number
revoked_certificates: List[RevokedCertificate] # List of revoked certificates
pem_crl: str # PEM-encoded CRL (output only)
access_url: str # CRL download URL (output only)
state: State # CRL state (output only)
create_time: timestamp_pb2.Timestamp # Creation time (output only)
update_time: timestamp_pb2.Timestamp # Last update time (output only)
revision_id: str # Revision identifier (output only)
labels: Dict[str, str] # Resource labels
class RevokedCertificate:
"""Information about a revoked certificate."""
certificate: str # Certificate resource name
hex_serial_number: str # Certificate serial number in hex
revocation_reason: RevocationReason # Reason for revocationclass State(Enum):
"""CRL states."""
STATE_UNSPECIFIED = 0 # Unspecified state
ACTIVE = 1 # CRL is active and current
SUPERSEDED = 2 # CRL has been superseded by newer versionfrom google.cloud.security.privateca import CertificateAuthorityServiceClient
client = CertificateAuthorityServiceClient()
# Get specific CRL
crl_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca/certificateRevocationLists/my-crl"
crl = client.get_certificate_revocation_list(name=crl_name)
print(f"CRL: {crl.name}")
print(f"Sequence number: {crl.sequence_number}")
print(f"State: {crl.state}")
print(f"Revoked certificates: {len(crl.revoked_certificates)}")
print(f"Access URL: {crl.access_url}")
if crl.revoked_certificates:
print("Revoked certificates:")
for revoked in crl.revoked_certificates:
print(f" Serial: {revoked.hex_serial_number}, Reason: {revoked.revocation_reason}")# List all CRLs for a CA
ca_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca"
crls = client.list_certificate_revocation_lists(parent=ca_name)
print(f"CRLs for CA {ca_name}:")
for crl in crls:
print(f" CRL: {crl.name}")
print(f" Sequence: {crl.sequence_number}")
print(f" State: {crl.state}")
print(f" Created: {crl.create_time}")
print(f" Updated: {crl.update_time}")
print(f" Revoked certs: {len(crl.revoked_certificates)}")
print()from google.protobuf import field_mask_pb2
# Update CRL labels
crl_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca/certificateRevocationLists/my-crl"
updated_crl = CertificateRevocationList(
name=crl_name,
labels={
"environment": "production",
"ca-type": "root",
"auto-update": "enabled"
}
)
update_mask = field_mask_pb2.FieldMask(paths=["labels"])
operation = client.update_certificate_revocation_list(
certificate_revocation_list=updated_crl,
update_mask=update_mask
)
result = operation.result()
print(f"Updated CRL: {result.name}")
print(f"New labels: {result.labels}")import requests
from cryptography import x509
from cryptography.hazmat.primitives import serialization
# Get CRL and download the actual CRL data
crl_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca/certificateRevocationLists/my-crl"
crl = client.get_certificate_revocation_list(name=crl_name)
if crl.access_url:
# Download CRL from access URL
response = requests.get(crl.access_url)
crl_data = response.content
# Parse CRL using cryptography library
parsed_crl = x509.load_der_x509_crl(crl_data)
print(f"CRL Issuer: {parsed_crl.issuer}")
print(f"This Update: {parsed_crl.this_update}")
print(f"Next Update: {parsed_crl.next_update}")
print(f"Revoked certificates: {len(list(parsed_crl))}")
# Process revoked certificates
for revoked_cert in parsed_crl:
print(f" Serial: {revoked_cert.serial_number}")
print(f" Revocation Date: {revoked_cert.revocation_date}")
if revoked_cert.extensions:
for ext in revoked_cert.extensions:
print(f" Extension: {ext.oid}")
# Use PEM format if available
if crl.pem_crl:
print(f"PEM CRL:\n{crl.pem_crl}")
# Parse PEM CRL
pem_crl = x509.load_pem_x509_crl(crl.pem_crl.encode())
print(f"PEM CRL has {len(list(pem_crl))} revoked certificates")from datetime import datetime, timezone
def monitor_crl_updates(ca_name: str):
"""Monitor CRL updates for a certificate authority."""
crls = client.list_certificate_revocation_lists(parent=ca_name)
for crl in crls:
# Convert timestamp to datetime
update_time = datetime.fromtimestamp(
crl.update_time.seconds + crl.update_time.nanos / 1e9,
tz=timezone.utc
)
# Check if CRL is recent (within last 24 hours)
time_diff = datetime.now(timezone.utc) - update_time
hours_old = time_diff.total_seconds() / 3600
print(f"CRL: {crl.name}")
print(f" State: {crl.state}")
print(f" Last updated: {update_time} ({hours_old:.1f} hours ago)")
print(f" Revoked certificates: {len(crl.revoked_certificates)}")
if hours_old > 24:
print(f" ⚠️ Warning: CRL is over 24 hours old")
if crl.state != CertificateRevocationList.State.ACTIVE:
print(f" ⚠️ Warning: CRL is not active")
print()
# Monitor CRLs for a CA
ca_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca"
monitor_crl_updates(ca_name)def check_certificate_revocation(certificate_serial: str, ca_name: str) -> bool:
"""Check if a certificate is revoked using CRL."""
crls = client.list_certificate_revocation_lists(parent=ca_name)
for crl in crls:
if crl.state == CertificateRevocationList.State.ACTIVE:
for revoked_cert in crl.revoked_certificates:
if revoked_cert.hex_serial_number.upper() == certificate_serial.upper():
print(f"Certificate {certificate_serial} is REVOKED")
print(f"Revocation reason: {revoked_cert.revocation_reason}")
return True
print(f"Certificate {certificate_serial} is NOT revoked")
return False
# Check specific certificate
cert_serial = "1234567890ABCDEF"
ca_name = "projects/my-project/locations/us-central1/caPools/my-ca-pool/certificateAuthorities/my-ca"
is_revoked = check_certificate_revocation(cert_serial, ca_name)Install with Tessl CLI
npx tessl i tessl/pypi-google-cloud-private-ca