Skip to content

Add --ca-cert CLI Flag for Custom Certificate Authorities #18

@shakrav2

Description

@shakrav2

Problem

Users connecting to HTTPS endpoints secured with certificates signed by custom or private Certificate Authorities (common in enterprise environments) cannot establish connections because aepcli only trusts system-installed CA certificates.

Current behavior:

$ aepcli myapi resources list
Error: Get "https://api.internal": x509: certificate signed by unknown authority

Impact: Enterprise users cannot connect to internal APIs that use certificates signed by organizational Certificate Authorities.

Motivation

Enterprise and organizational environments frequently use internal Certificate Authorities to sign certificates for internal services. While adding the CA certificate to the system trust store is the standard approach, this is not always practical or possible:

Enterprise environment constraints:

  • Developers often lack administrative privileges to modify system trust stores in managed workstations
  • Corporate security policies may restrict or prohibit system-level certificate modifications
  • Centrally-managed environments require IT approval for trust store changes

Development workflow challenges:

  • Containerized development environments don't persist trust store changes between rebuilds
  • CI/CD pipelines may not have permissions to modify runner trust stores
  • Multi-environment testing (dev, staging, prod) may use different CAs

Cross-platform complexity:

  • Trust store locations and modification procedures vary significantly across Windows, macOS, and Linux
  • System trust store changes are global and may affect other applications

Developers need a non-privileged, portable way to specify custom CA certificates without requiring system-level changes or administrative approval.

Similar features in other CLI tools:

  • kubectl: --certificate-authority
  • curl: --cacert
  • aws-cli: --ca-bundle
  • docker: --tlscacert
  • git: http.sslCAInfo

User Story

As a developer working with internal enterprise APIs,
I want to specify a custom CA certificate via a CLI flag,
So that I can connect to HTTPS endpoints secured by my organization's Certificate Authority without modifying system trust stores.

Proposed Solution

Add a --ca-cert <file> CLI flag that:

  • Accepts a path to a PEM-encoded CA certificate file
  • Adds the certificate to the trusted CA pool (additive to system CAs)
  • Does not replace or remove system CA certificates
  • Validates the certificate file format before use
  • Provides clear error messages for invalid or missing files

Key principle: Custom CA certificates should be added to the system CA pool, not replace it. This ensures connections to public HTTPS endpoints (e.g., github.com) continue to work normally.

Expected Behavior

Without flag (default - only system CAs trusted):

$ aepcli myapi resources list
Error: Get "https://api.internal": x509: certificate signed by unknown authority

With flag (custom CA added to trust pool):

$ aepcli --ca-cert /etc/ssl/certs/corporate-ca.pem myapi resources list
{
  "resources": [...]
}

With flag pointing to non-existent file:

$ aepcli --ca-cert /path/does-not-exist.pem myapi resources list
Error: Failed to read CA certificate from /path/does-not-exist.pem: file does not exist

To fix this issue:
  1. Verify the file path is correct
  2. Ensure the file exists and is readable
  3. Verify the file contains a valid PEM-encoded certificate

Use 'openssl x509 -in /path/to/ca.pem -text -noout' to verify the certificate.

With flag pointing to invalid PEM file:

$ aepcli --ca-cert /path/invalid.pem myapi resources list
Error: Failed to parse CA certificate from /path/invalid.pem: not valid PEM format

Expected PEM format:
  -----BEGIN CERTIFICATE-----
  ...
  -----END CERTIFICATE-----

Use 'openssl x509 -in /path/to/ca.pem -text -noout' to verify the certificate.

Combined with other flags:

$ aepcli --ca-cert /etc/ssl/corporate-ca.pem --log-http myapi resources create foo --name="test"
Request: POST https://api.internal/resources
...

Public HTTPS endpoints still work:

# System CAs are preserved, so public endpoints work normally
$ aepcli --ca-cert /etc/ssl/corporate-ca.pem github-api repos list
# Successfully connects using public CA (DigiCert, Let's Encrypt, etc.)

Acceptance Criteria

  • --ca-cert <file> flag is available as a persistent flag
  • Flag accepts a file path to a PEM-encoded certificate
  • Custom CA certificate is added to system CA pool (not replaced)
  • System CA certificates continue to work (connections to public HTTPS endpoints succeed)
  • Validates certificate file exists before attempting to load
  • Validates PEM format and provides clear error for invalid files
  • Provides helpful error messages with remediation steps
  • Connections to endpoints using custom CA succeed
  • Connections to endpoints using public CAs continue to work
  • Debug logging shows when custom CA is loaded (when --log-level=debug)
  • Flag can be combined with all other existing flags
  • Unit tests validate certificate loading and validation
  • Integration tests verify connections with custom CA certificates
  • Documentation includes usage examples and troubleshooting guide

Certificate File Format

The flag must accept standard PEM-encoded X.509 certificates:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKL0UG+mRkSvMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
...
-----END CERTIFICATE-----

Supported formats:

  • Single certificate per file
  • PEM encoding (Base64 with -----BEGIN CERTIFICATE----- header)

Not supported in this issue (future enhancements):

  • Multiple certificates in one file (certificate chains)
  • DER-encoded certificates
  • PKCS#7 or PKCS#12 formats
  • Certificate directories

Error Messages

All error messages should be actionable and guide users to resolution:

Missing file:

Error: Failed to read CA certificate from <path>: file does not exist

To fix this issue:
  1. Verify the file path is correct
  2. Ensure the file exists and is readable

Invalid PEM format:

Error: Failed to parse CA certificate from <path>: not valid PEM format

Expected format:
  -----BEGIN CERTIFICATE-----
  ...
  -----END CERTIFICATE-----

Use 'openssl x509 -in <path> -text -noout' to verify the certificate.

Permission denied:

Error: Failed to read CA certificate from <path>: permission denied

To fix this issue:
  1. Verify you have read permissions for the file
  2. Check file permissions with: ls -l <path>

Debug Logging

When --log-level=debug is set, log certificate loading:

$ aepcli --log-level=debug --ca-cert /etc/ssl/corporate-ca.pem myapi resources list
DEBUG: Loading TLS configuration
DEBUG: System CA certificates loaded from system trust store
DEBUG: Custom CA certificate loaded from /etc/ssl/corporate-ca.pem
DEBUG: Connecting to https://api.internal
...

Out of Scope

The following are explicitly out of scope for this issue and will be addressed separately:

  • Environment variable support (e.g., AEPCLI_CA_CERT, SSL_CERT_FILE)
  • Configuration file support (per-API or global CA certs)
  • Multiple --ca-cert flags (loading multiple CA certificates)
  • Certificate directories (e.g., --ca-cert-dir)
  • Certificate chains or intermediate certificates
  • Client certificate authentication (mTLS)
  • Certificate pinning
  • TLS version or cipher configuration

Security Considerations

This feature improves security by enabling proper certificate verification:

  1. Additive trust model: Custom CA certificates are added to the system CA pool, not replacing it. This ensures:

    • Public HTTPS endpoints continue to work normally
    • Standard security practices are preserved
    • No reduction in security for public endpoints
  2. Certificate validation: Files are validated before use to prevent confusing errors later in the TLS handshake

  3. No privilege escalation: Does not require administrative privileges or system modifications

  4. User responsibility: Users are responsible for:

    • Securing their CA certificate files (recommended: chmod 644 or chmod 600)
    • Verifying they trust the CA certificate being added
    • Understanding the security implications of trusting a custom CA
  5. Transparency: Debug logging shows which certificates are loaded for troubleshooting

Related Issues

  • #TBD - Add environment variable support for CA certificates (AEPCLI_CA_CERT, SSL_CERT_FILE)
  • #TBD - Add config file support for CA certificates
  • #TBD - Add support for multiple CA certificates
  • #TBD - Add support for CA certificate directories

References

Additional Context

This is the proper, secure solution for connecting to endpoints with custom Certificate Authorities. Unlike --insecure-skip-tls-verify (which disables security), this feature maintains full certificate verification while trusting additional CAs.

This is the first step in a series of CA certificate support enhancements. Future improvements will add:

  • Environment variable support (for CI/CD and containerized workflows)
  • Config file support (for persistent per-API configuration)
  • Multiple certificate support (for complex CA hierarchies)
  • Certificate directory support (for managing many CA certificates)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions