Update: replace hash symlink with CA bundle for certificate verification
All checks were successful
/ test (push) Successful in 17s
All checks were successful
/ test (push) Successful in 17s
This commit is contained in:
@@ -23,7 +23,7 @@ make_ca [--days <validity_days>] [--issuing-ca <name>] <ca_directory> <ca_name>
|
||||
- `--days <validity_days>`: Optional. The number of days the CA certificate will be valid. Default is 3650 days (10 years).
|
||||
- `--issuing-ca <name>`: Optional. If specified, creates an intermediate CA with <ca_name> as the intermediate CA name and using <name> as certificate and key file prefix for the issuing CA (instead of root's `ca`).
|
||||
|
||||
It also creates a *hash link* symbolic link for the CA certificate, which is required by OpenSSL when using the `verify` command with `-CApath` option.
|
||||
It also maintains a `ca_bundle.pem` file in the CA directory containing the root CA and any issuing CA certificates concatenated together. Use this bundle with `openssl verify -CAfile <ca_directory>/ca_bundle.pem` instead of relying on hash symlinks — this works identically on Linux, macOS, and Windows without symlink privileges.
|
||||
|
||||
### `make_cert()`
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ function display_certificate() {
|
||||
openssl x509 -in "$CERT_PATH" -noout -subject -issuer -serial -fingerprint
|
||||
echo
|
||||
|
||||
echo -e "\nVerifying certificate against the CA ($CA_DIR)..."
|
||||
echo -e "\nVerifying certificate against the CA bundle ($CA_DIR/ca_bundle.pem)..."
|
||||
|
||||
# Verify the certificate against the CA
|
||||
if openssl verify -CApath "$CA_DIR" "$CERT_PATH" 2>/dev/null; then
|
||||
# Verify the certificate against the CA bundle
|
||||
if openssl verify -CAfile "$CA_DIR/ca_bundle.pem" "$CERT_PATH" 2>/dev/null; then
|
||||
echo "Certificate verification successful."
|
||||
else
|
||||
echo "ERROR: Certificate verification failed." >&2
|
||||
|
||||
47
simple-ca.py
47
simple-ca.py
@@ -33,32 +33,23 @@ def _err(msg):
|
||||
print(f"ERROR: {msg}", file=sys.stderr)
|
||||
|
||||
|
||||
def make_hash_link(cert_path):
|
||||
if not os.path.isfile(cert_path):
|
||||
_err(f"Certificate file {cert_path} does not exist.")
|
||||
return False
|
||||
|
||||
cert_dir = os.path.dirname(cert_path)
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["openssl", "x509", "-in", cert_path, "-noout", "-hash"],
|
||||
capture_output=True, text=True, check=True,
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
_err(f"Failed to calculate hash for certificate {cert_path}.")
|
||||
return False
|
||||
|
||||
cert_hash = result.stdout.strip()
|
||||
if not cert_hash:
|
||||
_err(f"Failed to calculate hash for certificate {cert_path}.")
|
||||
return False
|
||||
|
||||
link_path = os.path.join(cert_dir, f"{cert_hash}.0")
|
||||
target = os.path.basename(cert_path)
|
||||
if os.path.islink(link_path) or os.path.exists(link_path):
|
||||
os.remove(link_path)
|
||||
os.symlink(target, link_path)
|
||||
return True
|
||||
def _rebuild_ca_bundle(ca_dir):
|
||||
"""Write ca_bundle.pem = root cert + any issuing CA certs in this dir."""
|
||||
bundle_path = os.path.join(ca_dir, "ca_bundle.pem")
|
||||
parts = []
|
||||
root = os.path.join(ca_dir, "ca_cert.pem")
|
||||
if os.path.isfile(root):
|
||||
with open(root, "rb") as f:
|
||||
parts.append(f.read())
|
||||
for name in sorted(os.listdir(ca_dir)):
|
||||
if name == "ca_cert.pem" or not name.endswith("_cert.pem"):
|
||||
continue
|
||||
path = os.path.join(ca_dir, name)
|
||||
if os.path.isfile(path):
|
||||
with open(path, "rb") as f:
|
||||
parts.append(f.read())
|
||||
with open(bundle_path, "wb") as f:
|
||||
f.write(b"".join(parts))
|
||||
|
||||
|
||||
def make_ca(ca_dir, ca_name, days=3650, issuing_ca=None, aia_base_url=None):
|
||||
@@ -119,7 +110,7 @@ def make_ca(ca_dir, ca_name, days=3650, issuing_ca=None, aia_base_url=None):
|
||||
_err("Failed to generate CA certificate and key.")
|
||||
return False
|
||||
|
||||
make_hash_link(root_ca_cert_path)
|
||||
_rebuild_ca_bundle(ca_dir)
|
||||
|
||||
if aia_base_url:
|
||||
with open(aia_file, "w") as f:
|
||||
@@ -157,7 +148,7 @@ def make_ca(ca_dir, ca_name, days=3650, issuing_ca=None, aia_base_url=None):
|
||||
_err("Failed to generate issuing CA certificate and key.")
|
||||
return False
|
||||
|
||||
make_hash_link(ca_cert_path)
|
||||
_rebuild_ca_bundle(ca_dir)
|
||||
|
||||
if aia_base_url:
|
||||
with open(aia_file, "w") as f:
|
||||
|
||||
32
simple-ca.sh
32
simple-ca.sh
@@ -22,19 +22,19 @@
|
||||
|
||||
# These functions require Bash and OpenSSL to be installed on the system.
|
||||
|
||||
function make_hash_link() {
|
||||
local CERT_PATH="$1"
|
||||
if [[ ! -f "$CERT_PATH" ]]; then
|
||||
echo "ERROR: Certificate file $CERT_PATH does not exist." >&2
|
||||
return 1
|
||||
function _rebuild_ca_bundle() {
|
||||
local CA_DIR="$1"
|
||||
local BUNDLE="$CA_DIR/ca_bundle.pem"
|
||||
: > "$BUNDLE"
|
||||
if [[ -f "$CA_DIR/ca_cert.pem" ]]; then
|
||||
cat "$CA_DIR/ca_cert.pem" >> "$BUNDLE"
|
||||
fi
|
||||
local CERT_DIR="$(dirname "$CERT_PATH")"
|
||||
local HASH="$(openssl x509 -in "$CERT_PATH" -noout -hash 2>/dev/null)"
|
||||
if [[ -z "$HASH" ]]; then
|
||||
echo "ERROR: Failed to calculate hash for certificate $CERT_PATH." >&2
|
||||
return 1
|
||||
fi
|
||||
ln -sf "$(basename "$CERT_PATH")" "$CERT_DIR/${HASH}.0"
|
||||
local f
|
||||
for f in "$CA_DIR"/*_cert.pem; do
|
||||
[[ -f "$f" ]] || continue
|
||||
[[ "$(basename "$f")" == "ca_cert.pem" ]] && continue
|
||||
cat "$f" >> "$BUNDLE"
|
||||
done
|
||||
}
|
||||
|
||||
function make_ca() {
|
||||
@@ -129,8 +129,8 @@ function make_ca() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Make a "hash" symlink for the CA certificate to allow OpenSSL to find it when verifying other certificates
|
||||
make_hash_link "$CA_DIR/$ROOT_CA_CERT"
|
||||
# Rebuild the CA bundle (root + any issuing CAs) for use with `openssl verify -CAfile`
|
||||
_rebuild_ca_bundle "$CA_DIR"
|
||||
|
||||
if [[ -n "$AIA_BASE_URL" ]]; then
|
||||
echo "$AIA_BASE_URL" > "$CA_DIR/aia_base_url.txt"
|
||||
@@ -162,8 +162,8 @@ function make_ca() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make a "hash" symlink for the issuing CA certificate to allow OpenSSL to find it when verifying other certificates
|
||||
make_hash_link "$CA_DIR/${CA_CERT}"
|
||||
# Rebuild the CA bundle (root + any issuing CAs) for use with `openssl verify -CAfile`
|
||||
_rebuild_ca_bundle "$CA_DIR"
|
||||
|
||||
if [[ -n "$AIA_BASE_URL" ]]; then
|
||||
echo "$AIA_BASE_URL" > "$CA_DIR/aia_base_url.txt"
|
||||
|
||||
Reference in New Issue
Block a user