When implementing client certificate authentication in Apache, handling multiple Certificate Authorities (CAs) can be tricky. The SSLCACertificatePath directive provides one approach, but the hash symlink requirement often causes confusion.
There are two main approaches to specify trusted CAs:
# Single file approach (recommended for most cases)
SSLCACertificateFile /path/to/all_cas.pem
# Directory approach (requires hashed symlinks)
SSLCACertificatePath /path/to/ca_directory/
When using SSLCACertificatePath, each CA certificate must have a properly hashed symlink. The hash is derived from the certificate's subject and must follow OpenSSL's naming convention.
The easiest way to generate these links is using OpenSSL's c_rehash utility:
# First, ensure all CA certs are in individual PEM files
cd /path/to/ca_directory/
c_rehash .
This will create symlinks like:
3ab34d52.0 -> some_ca.crt
7f89e12a.0 -> another_ca.crt
For most use cases, combining all CA certificates into a single PEM file is simpler:
# Combine multiple CA certs into one file
cat ca1.pem ca2.pem ca3.pem > combined_cas.pem
# Apache configuration
SSLVerifyClient require
SSLVerifyDepth 2
SSLCACertificateFile /path/to/combined_cas.pem
Here's a complete virtual host example accepting client certificates from multiple CAs:
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
# Client certificate settings
SSLVerifyClient require
SSLVerifyDepth 2
# Using combined file approach
SSLCACertificateFile /etc/ssl/certs/trusted_cas.pem
# Alternative directory approach
# SSLCACertificatePath /etc/ssl/certs/ca_directory/
# Other settings
SSLOptions +StdEnvVars +ExportCertData
</VirtualHost>
If you encounter issues:
- Verify certificate chain completeness
- Check file permissions (Apache needs read access)
- Ensure all certificates are in PEM format
- Test with OpenSSL command line first:
openssl verify -CApath /your/ca/path client.crt
The directory approach (SSLCACertificatePath) can be slightly faster with very large numbers of CAs, as OpenSSL can perform hash-based lookups. However, for most implementations with <100 CAs, the single file approach performs equally well with simpler maintenance.
When configuring Apache to accept client certificates from multiple Certificate Authorities, the SSLCACertificatePath
directive requires special handling. Unlike SSLCACertificateFile
which accepts concatenated PEM certificates, the Path directive expects:
- Individual CA certificate files
- Hashed symbolic links created using OpenSSL
- Proper directory structure with 755 permissions
Here's the step-by-step process to prepare your CA certificate directory:
# Create directory for CA certs
sudo mkdir /etc/apache2/ssl.crt/ca/
sudo chmod 755 /etc/apache2/ssl.crt/ca/
# Add your CA certificates
sudo cp ca1.pem /etc/apache2/ssl.crt/ca/
sudo cp ca2.pem /etc/apache2/ssl.crt/ca/
# Generate hashed symlinks
sudo openssl x509 -noout -hash -in ca1.pem
# Output will be something like "3a2b1c0d"
sudo ln -s ca1.pem /etc/apache2/ssl.crt/ca/3a2b1c0d.0
For most modern implementations, concatenating multiple CA certificates into a single file using SSLCACertificateFile
is preferred:
# Combine multiple CA certs into one file
cat ca1.pem ca2.pem ca3.pem > combined-ca.crt
# Apache configuration
SSLVerifyClient require
SSLVerifyDepth 2
SSLCACertificateFile "/path/to/combined-ca.crt"
- Always verify certificate chains with
openssl verify -CApath /your/ca/path
- Remember to restart Apache after configuration changes
- Set appropriate
SSLVerifyDepth
based on your certificate chain length - Consider using environment variables for dynamic CA selection
If you encounter problems, check:
# Verify SSL configuration
apachectl configtest
apachectl -S
# Check error logs
tail -f /var/log/apache2/error.log
Common error patterns include:
- SSL3_GET_CLIENT_CERTIFICATE:no certificate returned (client didn't present cert)
- SSL Library Error: unable to get local issuer certificate (CA not properly configured)