Last active
April 19, 2024 13:57
-
-
Save dgunning/506d51914f3342cf487252d384a960bf to your computer and use it in GitHub Desktop.
Check if a certificate exists
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import certifi | |
from cryptography import x509 | |
from cryptography.hazmat.backends import default_backend | |
from cryptography.hazmat.primitives import hashes | |
from cryptography.hazmat.primitives.serialization import Encoding | |
def load_certificates_from_file(file_path): | |
"""Load all certificates from a file, automatically handling PEM and DER formats.""" | |
certs = [] | |
with open(file_path, 'rb') as file: | |
file_data = file.read() | |
if b'-----BEGIN CERTIFICATE-----' in file_data: | |
# Process as PEM | |
pem_data = file_data.split(b'-----END CERTIFICATE-----') | |
for data in pem_data: | |
if b'-----BEGIN CERTIFICATE-----' in data: | |
cert_data = data + b'-----END CERTIFICATE-----' | |
certs.append(x509.load_pem_x509_certificate(cert_data, default_backend())) | |
else: | |
# Process as DER | |
certs.append(x509.load_der_x509_certificate(file_data, default_backend())) | |
return certs | |
def read_certificate(file_path): | |
"""Read a single certificate from a file, detecting PEM or DER format.""" | |
with open(file_path, 'rb') as file: | |
cert_data = file.read() | |
if b'-----BEGIN CERTIFICATE-----' in cert_data: | |
return x509.load_pem_x509_certificate(cert_data, default_backend()) | |
else: | |
return x509.load_der_x509_certificate(cert_data, default_backend()) | |
def check_certificate_exists(target_cert, bundle_certs): | |
"""Check if the target certificate exists in the list of bundle certificates by comparing fingerprints.""" | |
target_fingerprint = target_cert.fingerprint(hashes.SHA256()) | |
for cert in bundle_certs: | |
if cert.fingerprint(hashes.SHA256()) == target_fingerprint: | |
return True | |
return False | |
def add_certificate_to_bundle(cert, bundle_path): | |
"""Add a certificate to the PEM bundle.""" | |
with open(bundle_path, 'ab') as bundle_file: | |
bundle_file.write(cert.public_bytes(Encoding.PEM)) | |
if __name__ == "__main__": | |
if len(sys.argv) != 2: | |
print("Usage: python check_cert.py <certificate_file>") | |
sys.exit(1) | |
cert_file_path = sys.argv[1] | |
cacert_file_path = certifi.where() # Use certifi to get the CA bundle path | |
# Load the target certificate and all certificates from the CA bundle | |
target_cert = read_certificate(cert_file_path) | |
bundle_certs = load_certificates_from_file(cacert_file_path) | |
# Check if the target certificate is in the CA bundle | |
exists = check_certificate_exists(target_cert, bundle_certs) | |
if exists: | |
print("Certificate already exists in the CA certificate file.") | |
else: | |
print("Certificate does not exist in the CA certificate file.") | |
user_input = input("Do you want to add this certificate to the CA bundle? (yes/no): ") | |
if user_input.lower() == 'yes': | |
add_certificate_to_bundle(target_cert, cacert_file_path) | |
print("Certificate has been added to the CA bundle.") | |
else: | |
print("Certificate was not added.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import os | |
def get_certificate_by_name(common_name): | |
"""Retrieve a certificate from the macOS Keychain by common name.""" | |
try: | |
# Define the path to the system keychain | |
keychain_path = "/Library/Keychains/System.keychain" | |
# Prepare the command to search the certificate | |
cmd = [ | |
"security", | |
"find-certificate", | |
"-c", common_name, | |
"-p", # Output in PEM format | |
keychain_path | |
] | |
# Execute the command | |
result = subprocess.run(cmd, capture_output=True, text=True) | |
# Check for errors | |
if result.returncode != 0: | |
print("Error:", result.stderr) | |
return None | |
# Return the certificate data | |
return result.stdout | |
except Exception as e: | |
print("An error occurred:", e) | |
return None | |
# Example usage | |
cert_name = "Apple Root CA" | |
certificate = get_certificate_by_name(cert_name) | |
if certificate: | |
print("Certificate Found:\n", certificate) | |
else: | |
print("No certificate found with the name:", cert_name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import os | |
def get_certificate_by_name(common_name): | |
"""Retrieve a certificate from the macOS Keychain by common name.""" | |
try: | |
# Define the path to the system keychain | |
keychain_path = "/Library/Keychains/System.keychain" | |
# Prepare the command to search the certificate | |
cmd = [ | |
"security", | |
"find-certificate", | |
"-c", common_name, | |
"-p", # Output in PEM format | |
keychain_path | |
] | |
# Execute the command | |
result = subprocess.run(cmd, capture_output=True, text=True) | |
# Check for errors | |
if result.returncode != 0: | |
print("Error:", result.stderr) | |
return None | |
# Return the certificate data | |
return result.stdout | |
except Exception as e: | |
print("An error occurred:", e) | |
return None | |
# Example usage | |
cert_name = "Apple Root CA" | |
certificate = get_certificate_by_name(cert_name) | |
if certificate: | |
print("Certificate Found:\n", certificate) | |
else: | |
print("No certificate found with the name:", cert_name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ssl | |
import socket | |
from OpenSSL import crypto | |
def get_certificate_chain(host, port=443): | |
""" Fetch the entire certificate chain from the server. """ | |
context = ssl.create_default_context() | |
conn = context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=host) | |
cert_chain = [] | |
try: | |
conn.connect((host, port)) | |
for cert_bin in conn.getpeercert(binary_form=False)['caIssuers']: | |
x509 = crypto.load_certificate(crypto.FILETYPE_ASN1, cert_bin) | |
cert_chain.append(x509) | |
return cert_chain | |
except Exception as e: | |
print(f"An error occurred: {e}") | |
finally: | |
conn.close() | |
def find_certificate_by_name(cert_chain, name): | |
""" Find and return the certificate that matches the given name. """ | |
for cert in cert_chain: | |
subject = dict(cert.get_subject().get_components()) | |
if subject[b'CN'] == name.encode(): | |
return cert | |
return None | |
# Example usage: | |
chain = get_certificate_chain('www.google.com') | |
target_cert = find_certificate_by_name(chain, 'Google Trust Services') | |
if target_cert: | |
print("Certificate Found:") | |
print(crypto.dump_certificate(crypto.FILETYPE_PEM, target_cert).decode('utf-8')) | |
else: | |
print("No matching certificate found.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import os | |
def get_certificate_by_name(common_name): | |
"""Retrieve a certificate from the macOS Keychain by common name.""" | |
try: | |
# Define the path to the system keychain | |
keychain_path = "/Library/Keychains/System.keychain" | |
# Prepare the command to search the certificate | |
cmd = [ | |
"security", | |
"find-certificate", | |
"-c", common_name, | |
"-p", # Output in PEM format | |
keychain_path | |
] | |
# Execute the command | |
result = subprocess.run(cmd, capture_output=True, text=True) | |
# Check for errors | |
if result.returncode != 0: | |
print("Error:", result.stderr) | |
return None | |
# Return the certificate data | |
return result.stdout | |
except Exception as e: | |
print("An error occurred:", e) | |
return None | |
# Example usage | |
cert_name = "Apple Root CA" | |
certificate = get_certificate_by_name(cert_name) | |
if certificate: | |
print("Certificate Found:\n", certificate) | |
else: | |
print("No certificate found with the name:", cert_name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import virtualenv | |
import os | |
import subprocess | |
import pytest | |
def create_virtual_env(path): | |
"""Create a virtual environment in a specified directory and return the path to it.""" | |
session = virtualenv.cli_run([str(path)]) | |
return session.creator.dest # Correctly accessing the path to the created virtual environment | |
def install_dependencies(env_dir): | |
"""Install required dependencies in the virtual environment.""" | |
subprocess.run([os.path.join(env_dir, 'bin', 'pip'), 'install', '--upgrade', 'pip'], check=True) | |
subprocess.run([os.path.join(env_dir, 'bin', 'pip'), 'install', 'certifi'], check=True) | |
def run_fixcert_script(env_dir, cert_file): | |
"""Run the fixcert.py script to add the certificate to cacerts.""" | |
python_exec = os.path.join(env_dir, 'bin', 'python') | |
subprocess.run([python_exec, 'fixcert.py', cert_file], check=True) | |
def certificate_in_cacerts(env_dir, cert_content): | |
"""Check if the certificate content is in the cacerts.pem file used by certifi.""" | |
import certifi | |
cacert_path = certifi.where() | |
with open(cacert_path, 'r') as f: | |
cacerts_content = f.read() | |
return cert_content in cacerts_content | |
@pytest.fixture | |
def setup_env(tmp_path): | |
"""Fixture to set up and tear down a virtual environment.""" | |
env_path = tmp_path / "venv" | |
env_dir = create_virtual_env(env_path) | |
install_dependencies(env_dir) | |
yield env_dir | |
def test_certificate_installation(setup_env): | |
cert_content = "-----BEGIN CERTIFICATE-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzclLq9Xe2tcQg9Rgvec4E\n-----END CERTIFICATE-----" | |
cert_file = os.path.join(setup_env, 'temp_cert.pem') | |
with open(cert_file, 'w') as f: | |
f.write(cert_content) | |
run_fixcert_script(setup_env, cert_file) | |
assert certificate_in_cacerts(setup_env, cert_content), "Certificate was not found in cacerts." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment