How to Install a Custom Root CA Certificate on CentOS 6 for Apache, OpenLDAP, and Node.js Services


2 views

Working with custom root certificates on CentOS 6 requires understanding its legacy certificate storage system. The primary certificate bundle lives at:

/etc/pki/tls/certs/ca-bundle.crt

However, simply appending your certificate here might not suffice for all services due to CentOS 6's aging components.

For system-wide trust, we need a multi-pronged approach:

# Copy your CA cert to the trusted store
sudo cp your_root_ca.crt /etc/pki/ca-trust/source/anchors/

# Update the trust store
sudo update-ca-trust extract

This handles the base system trust, but we need service-specific configurations.

For Apache and PHP cURL operations, ensure these settings in your virtual host or php.ini:

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /path/to/your/cert.pem
    SSLCertificateKeyFile /path/to/your/key.pem
    SSLCACertificateFile /path/to/your/root_ca.crt
</VirtualHost>

For PHP applications making HTTPS requests:

// Set the CA path explicitly in PHP
curl_setopt($ch, CURLOPT_CAINFO, '/etc/pki/tls/certs/ca-bundle.crt');
// Or for custom CA
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/your/root_ca.crt');

For Net_LDAP2 and OpenLDAP clients, create or modify /etc/openldap/ldap.conf:

TLS_CACERT /path/to/your/root_ca.crt
TLS_REQCERT allow

For PEAR's Net_LDAP2, ensure the connection options include:

$ldap = Net_LDAP2::connect(array(
    'host' => 'ldap.example.com',
    'tls' => true,
    'options' => array(
        'LDAP_OPT_X_TLS_CACERTFILE' => '/path/to/your/root_ca.crt'
    )
));

For Node.js applications like Parsoid, you have several options:

// Method 1: Set NODE_EXTRA_CA_CERTS environment variable
process.env.NODE_EXTRA_CA_CERTS = '/path/to/your/root_ca.crt';

// Method 2: Use the ca option in HTTPS requests
const https = require('https');
const fs = require('fs');

const options = {
  hostname: 'example.com',
  port: 443,
  path: '/',
  method: 'GET',
  ca: fs.readFileSync('/path/to/your/root_ca.crt')
};

https.request(options, (res) => {
  // Handle response
});

Test your configurations with these commands:

# Verify Apache SSL configuration
openssl s_client -connect localhost:443 -CAfile /path/to/your/root_ca.crt

# Test LDAP connectivity
ldapsearch -x -H ldaps://ldap.example.com -ZZ -v

# Check Node.js certificate acceptance
NODE_EXTRA_CA_CERTS=/path/to/your/root_ca.crt node -e "require('https').get('https://example.com', (res) => console.log(res.statusCode))"

Working with custom Certificate Authorities on CentOS 6 presents unique challenges due to its age and the evolving SSL/TLS landscape. Here's a comprehensive approach to ensure your root CA is properly recognized across different services.

First, let's handle the base system configuration. While /etc/pki/tls/certs/ca-bundle.crt seems like the obvious location, some services ignore this file:

# Copy your root CA certificate to the trusted store
sudo cp your_root_ca.crt /etc/pki/ca-trust/source/anchors/

# Update the trust store
sudo update-ca-trust extract

For Apache to recognize your CA, you need to modify the SSL configuration:

# Edit your SSL configuration file
<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /path/to/your/cert.pem
    SSLCertificateKeyFile /path/to/your/key.pem
    SSLCACertificateFile /path/to/your/root_ca.crt
    SSLVerifyClient optional
    SSLVerifyDepth 10
</VirtualHost>

PHP applications making HTTPS requests need proper CA verification:

// Set the CA path in your PHP code
curl_setopt($ch, CURLOPT_CAINFO, '/etc/pki/tls/certs/ca-bundle.crt');
curl_setopt($ch, CURLOPT_CAPATH, '/etc/pki/tls/certs');

// Or modify php.ini
; php.ini settings
curl.cainfo = "/etc/pki/tls/certs/ca-bundle.crt"
openssl.cafile = "/etc/pki/tls/certs/ca-bundle.crt"

For OpenLDAP with Net_LDAP2, you need to configure TLS specifically:

# ldap.conf configuration
TLS_CACERT /etc/pki/tls/certs/your_root_ca.crt
TLS_REQCERT allow

In your PHP code using Net_LDAP2:

$ldap_config = array(
    'binddn' => 'cn=admin,dc=example,dc=com',
    'bindpw' => 'password',
    'host' => 'ldap.example.com',
    'tls' => true,
    'options' => array(
        'LDAP_OPT_X_TLS_CACERTFILE' => '/etc/pki/tls/certs/your_root_ca.crt',
        'LDAP_OPT_X_TLS_REQUIRE_CERT' => LDAP_OPT_X_TLS_ALLOW
    )
);

For Node.js applications like Parsoid, you have several options:

// Method 1: Environment variable
process.env.NODE_EXTRA_CA_CERTS = '/etc/pki/tls/certs/your_root_ca.crt';

// Method 2: HTTPS agent configuration
const https = require('https');
const fs = require('fs');

const agent = new https.Agent({
    ca: fs.readFileSync('/etc/pki/tls/certs/your_root_ca.crt')
});

// Use the agent in your requests
https.get({
    hostname: 'internal.service',
    port: 443,
    path: '/',
    agent: agent
}, (res) => {
    // Handle response
});

After implementation, verify each component:

# Verify Apache
openssl s_client -connect localhost:443 -CAfile /etc/pki/tls/certs/your_root_ca.crt

# Verify OpenLDAP
ldapsearch -x -H ldaps://ldap.example.com -b "" -s base -ZZ

# Verify Node.js
NODE_DEBUG=tls,https node your_application.js

If services still don't recognize your CA:

  1. Check file permissions - certificates should be world-readable
  2. Ensure proper certificate chain - intermediate CAs may be needed
  3. Verify certificate formats - use PEM format for most Linux services
  4. Check service-specific documentation - some have unique requirements