In a previous blog post, I covered how to monitor SSL certificates by directly querying accessible endpoints. However, this approach has a significant limitation: it only captures certificates that are publicly accessible. Many certificates in your infrastructure may not have accessible endpoints, making them invisible to traditional monitoring approaches.
To solve this problem, I've developed a solution that combines live certificate scanning with DigiCert's API to create a comprehensive certificate inventory.
Visual Results
You can see the API discovered certificates as they are in yellow and do not contain the protocol and cipher as below:
The Challenge with Endpoint-Only Monitoring
Traditional SSL monitoring scripts work by connecting to specific hostnames and ports to retrieve certificate information:
# Example of endpoint-based certificate checking
openssl s_client -connect a6n.co.uk:443 -servername a6n.co.uk < /dev/null 2>/dev/null | openssl x509 -noout -dates
This method only works for certificates that are:
- Publicly accessible
- Bound to active services
- Not behind firewalls or internal networks
Many certificates in enterprise environments don't meet these criteria, creating blind spots in your monitoring.
Leveraging DigiCert's API
DigiCert provides a comprehensive API that allows you to retrieve all certificates associated with your account, regardless of whether they're accessible via traditional endpoints.
Note : I am using the USA API calls, if you are in a different region, you may need to use your localized version of that API framework!
Setting Up the DigiCert Extractor
First, I created a script to extract certificate data from DigiCert's API:
#!/bin/bash
# DigiCert Certificate Data Extractor
API_KEY="<apikey>"
API_BASE_URL="https://certcentral.digicert.com/services/v2"
OUTPUT_FILE="digicertapi.csv"
# API call to retrieve issued certificates
response=$(curl -s \
-H "X-DC-DEVKEY: $API_KEY" \
-H "Content-Type: application/json" \
"$API_BASE_URL/order/certificate?status=issued&per_page=1000&page=$page")
The script filters for only valid, non-expired certificates:
# Python snippet for processing certificate data
for order in orders:
certificate = order.get('certificate', {})
cert_status = order.get('status', 'unknown')
# Only process issued certificates
if cert_status != 'issued':
continue
days = calculate_days(valid_till, days_remaining)
# Skip expired certificates
if days is None or days <= 0:
continue
Understanding the DigiCert API Response
The DigiCert API returns certificate data in the following structure:
{
"id": 1502351286,
"certificate": {
"id": 2398777,
"serial_number": "026d0d1c50b0eeb1762679f25025a1f7",
"common_name": "ssl.croucher.cloud",
"dns_names": [
"ssl.croucher.cloud",
"ssl2.croucher.cloud",
"secure.croucher.cloud"
],
"valid_from": "2024-10-29",
"valid_till": "2025-10-24",
"days_remaining": 28
},
"status": "issued"
}
The key benefit here is the dns_names
array, which contains all Subject Alternative Names (SANs) associated with the certificate.
Merging Live Data with DigiCert API Data
The next challenge was merging the two data sources without duplicating information. I created a Python script that intelligently combines the datasets:
def merge_certificates(self):
# Start with all existing certificates from live scanning
for hostname, cert_data in self.existing_certs.items():
self.merged_certs.append(cert_data)
# Add certificates that exist in DigiCert but not in existing CSV
for hostname, digicert_data in self.digicert_certs.items():
if hostname not in self.existing_certs:
# Create new entry with DigiCert data
new_cert = {
'hostname': digicert_data.get('hostname', ''),
'common_name': digicert_data.get('common_name', ''),
'issuer': digicert_data.get('issuer', ''),
'expiry_date': digicert_data.get('expiry_date', ''),
'days_until_expiry': digicert_data.get('days_until_expiry', ''),
'status': digicert_data.get('status', ''),
'protocol': '', # Leave blank for DigiCert entries
'cipher': '' # Leave blank for DigiCert entries
}
self.merged_certs.append(new_cert)
Handling Subject Alternative Names (SANs)
One of the most valuable aspects of this approach is how it handles SANs. Each certificate can protect multiple hostnames, and the script creates individual entries for each:
# Extract all hostnames from DNS names
hostnames = dns_names if dns_names else [common_name]
for hostname in hostnames:
if hostname and hostname != 'N/A':
print(f'{hostname},{common_name},{issuer},{valid_till},{days},{status},N/A,N/A')
This means a single certificate protecting www.example.com
, api.example.com
, and mail.example.com
will appear as three separate rows in your dashboard, each showing the same parent certificate in the "Common Name" column.
Workflow Integration
The complete workflow is automated through a PowerShell script that coordinates all components:
# Execute all scripts in sequence on remote server
& $PlinkPath -ssh -batch -l $Username -pw $Password $RemoteHost "cd $RemotePath && ./ssl_checker.py && ./digicert_extractor.sh && ./dashboardv2.sh"
# Download the generated dashboard
& $PuttyPath -q -scp -l $Username -pw $Password $RemoteHost`:$RemotePath$RemoteFile $LocalTempFile
This ensures that:
- Live certificate scanning runs first
- DigiCert API data is extracted
- Data is merged and dashboard is generated
- Results are automatically transferred to the web server
Visual Differentiation in the Dashboard
The dashboard visually distinguishes between different data sources:
.highlight-new {
background-color: #fefce8 !important;
}
.missing-data {
color: #9ca3af;
font-style: italic;
}
Certificates sourced from DigiCert API (those without live protocol/cipher data) are highlighted in yellow, making it easy to identify which certificates came from which source.
All Data : One Dashboard
This approach provides several key advantages:
- Comprehensive Coverage: Every certificate in your DigiCert account is captured, regardless of accessibility.
- SAN Visibility: All Subject Alternative Names appear as individual entries, ensuring no protected hostname is overlooked.
- Data Source Clarity: Visual indicators show whether data came from live scanning or API extraction.
- Automated Execution: The entire process runs automatically, ensuring your certificate inventory stays current.
API Authentication
To use this solution, you'll need a DigiCert API key with read permissions. The key is configured in the script header:
API_KEY="<apikey>"
API_BASE_URL="https://certcentral.digicert.com/services/v2" # Use EU endpoint if applicable
The script only makes read-only API calls, ensuring no modifications are made to your DigiCert account.
Conclusion
By combining live certificate scanning with DigiCert's API, this solution eliminates the blind spots inherent in endpoint-only monitoring. The result is a comprehensive certificate dashboard that captures every certificate in your infrastructure, regardless of whether it's publicly accessible, and provides clear visibility into all protected hostnames through proper SAN handling.
The automated workflow ensures this comprehensive view stays current without manual intervention, providing the complete certificate visibility that enterprise environments require.