SSL/TLS Certificate Operations
Level 1: Padawan (Beginner) - "What’s This Certificate Thing?"
Time investment: 2-4 hours
Goal: Understand certificates and basic inspection
Core competencies:
# Basic TLS connection test
openssl s_client -connect host:443
# Read certificate details
openssl x509 -in cert.pem -text -noout
# Check expiry dates
openssl x509 -in cert.pem -dates -noout
# Quick HTTPS check
curl -vI https://host
# Quick cert grab
echo | openssl s_client -connect host:443 2>&1 | head -20
Conceptual understanding:
-
What a certificate is (identity + public key)
-
Certificate vs private key
-
Why HTTPS matters
-
Self-signed vs CA-signed certificates
-
Basic trust model
Red flags you’re still at Padawan level:
-
You don’t know the difference between .pem, .crt, .cer, .key
-
"Certificate expired" errors confuse you
-
You don’t understand certificate chains
-
Self-signed certificate warnings scare you
Graduation criteria:
-
Can inspect any certificate and understand the output
-
Know how to check expiration dates
-
Understand why browsers warn about self-signed certs
-
Can troubleshoot basic "certificate invalid" errors
Level 2: Knight (Intermediate) - "I Can Debug TLS Issues"
Time investment: 4-8 hours beyond Padawan
You’ve mastered: Everything in Level 1
Core competencies:
# TLS connection debugging - your daily bread
echo | openssl s_client -connect 10.50.1.21:2484 2>&1 | head -30
# Full certificate chain inspection
echo | openssl s_client -connect host:443 -showcerts 2>&1
# Test specific TLS version
openssl s_client -connect host:443 -tls1_2
openssl s_client -connect host:443 -tls1_3
# Check certificate chain
openssl s_client -connect host:443 2>&1 | grep -E "depth|verify"
# Extract certificate from server
echo | openssl s_client -connect host:443 2>&1 | \
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > cert.pem
# Verify certificate against CA
openssl verify -CAfile ca-bundle.crt server.crt
# Check if cert matches private key
openssl x509 -noout -modulus -in cert.pem | md5sum
openssl rsa -noout -modulus -in key.pem | md5sum
# If hashes match, they're a pair
Conceptual understanding:
-
TLS handshake process (ClientHello, ServerHello, etc.)
-
Certificate chains (Root CA → Intermediate → Server)
-
SNI (Server Name Indication) and why it matters
-
Certificate validation process
-
Common TLS errors and what they mean
Key error codes you understand:
# Self-signed certificate
verify error:num=18:self-signed certificate
# Expired certificate
verify error:num=10:certificate has expired
# Hostname mismatch
verify error:num=62:Hostname mismatch
# Unknown CA
verify error:num=19:self-signed certificate in certificate chain
# Chain incomplete
verify error:num=21:unable to verify the first certificate
Graduation criteria:
-
Can debug any TLS connection failure
-
Understand certificate chain validation
-
Know how to bypass validation for testing (and why not to in production)
-
Can extract and inspect certificates from live servers
Level 3: Master (Advanced) - "I Architect TLS Solutions"
Time investment: 8-15 hours beyond Knight
You’ve mastered: Everything in Levels 1-2
Core competencies:
# Generate self-signed certificate with SANs
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 \
-nodes -keyout server.key -out server.crt \
-subj "/CN=myserver.local" \
-addext "subjectAltName=DNS:myserver.local,DNS:*.myserver.local,IP:10.0.0.1"
# Create CSR for CA signing
openssl req -new -newkey rsa:4096 -nodes \
-keyout server.key -out server.csr \
-subj "/C=US/ST=CA/L=LA/O=MyOrg/CN=server.example.com"
# Sign CSR with your own CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365 -sha256
# Create PKCS12 bundle (for importing to Windows/browsers)
openssl pkcs12 -export -out server.p12 \
-inkey server.key -in server.crt -certfile ca.crt
# Convert between formats
openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
# Inspect PKCS12 bundle
openssl pkcs12 -in bundle.p12 -info -noout
# Test with client certificate
openssl s_client -connect host:443 \
-cert client.crt -key client.key -CAfile ca.crt
# Full TLS debug with all details
openssl s_client -connect host:443 -state -debug -msg
Conceptual understanding:
-
PKI architecture and trust hierarchies
-
Certificate extensions (SAN, Key Usage, Extended Key Usage)
-
OCSP and CRL (certificate revocation)
-
mTLS (mutual TLS / client certificates)
-
Certificate pinning
-
HSM integration concepts
You can troubleshoot:
-
ISE EAP-TLS authentication failures
-
Oracle DataConnect certificate validation
-
LDAPS certificate issues
-
Internal CA trust problems
-
Certificate chain ordering issues
Graduation criteria:
-
Can design and implement PKI for an organization
-
Understand certificate lifecycle management
-
Can troubleshoot complex multi-tier TLS issues
-
Know security implications of each decision
Quick Reference Card
# ============================================================
# SSL/TLS QUICK REFERENCE
# ============================================================
# CONNECTION TESTING
echo | openssl s_client -connect host:port 2>&1 | head -30
echo | openssl s_client -connect host:443 -servername hostname # SNI
openssl s_client -connect host:443 -tls1_2 # Force TLS 1.2
openssl s_client -connect host:443 -tls1_3 # Force TLS 1.3
# CERTIFICATE INSPECTION
openssl x509 -in cert.pem -text -noout # Full details
openssl x509 -in cert.pem -dates -noout # Expiry dates
openssl x509 -in cert.pem -subject -noout # Subject only
openssl x509 -in cert.pem -issuer -noout # Issuer only
openssl x509 -in cert.pem -fingerprint -noout # SHA1 fingerprint
# EXTRACT FROM SERVER
echo | openssl s_client -connect host:443 2>&1 | \
sed -n '/BEGIN CERT/,/END CERT/p' > cert.pem
# VERIFY CHAIN
openssl verify -CAfile ca.crt server.crt
openssl s_client -connect host:443 2>&1 | grep "Verify return"
# KEY/CERT MATCHING
openssl x509 -noout -modulus -in cert.pem | md5sum
openssl rsa -noout -modulus -in key.pem | md5sum
# GENERATE SELF-SIGNED
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 \
-nodes -keyout key.pem -out cert.pem -subj "/CN=hostname"
# FORMAT CONVERSION
openssl x509 -in cert.der -inform DER -out cert.pem # DER to PEM
openssl x509 -in cert.pem -outform DER -out cert.der # PEM to DER
openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem
# COMMON PORTS
443 - HTTPS
636 - LDAPS
993 - IMAPS
995 - POP3S
8443 - Alt HTTPS
2484 - Oracle TCPS (ISE DataConnect)
9060 - ISE ERS API
1. TLS Connection Debugging
The Essential Debug Command
This is your go-to command for any TLS issue:
echo | openssl s_client -connect host:port 2>&1 | head -30
Real example - ISE DataConnect (Oracle):
❯ echo | timeout 5 openssl s_client -connect 10.50.1.21:2484 2>&1 | head -30
Connecting to 10.50.1.21
Can't use SSL_get_servername
depth=0 O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev
verify error:num=18:self-signed certificate
verify return:1
depth=0 O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev
verify return:1
CONNECTED(00000003)
---
Certificate chain
0 s:O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev
i:O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev
a:PKEY: RSA, 2048 (bit); sigalg: sha256WithRSAEncryption
v:NotBefore: Jan 13 02:01:10 2026 GMT; NotAfter: Jan 13 02:01:10 2027 GMT
What this tells you:
-
CONNECTED= TLS handshake succeeded -
verify error:num=18= Self-signed certificate (expected for internal services) -
depth=0= Server certificate (not CA) -
Certificate details (CN, validity dates, key type)
Debug by TLS Version
# Test TLS 1.2 (most common)
openssl s_client -connect host:443 -tls1_2
# Test TLS 1.3 (modern)
openssl s_client -connect host:443 -tls1_3
# Force specific cipher
openssl s_client -connect host:443 -cipher 'AES256-SHA'
# List available ciphers
openssl ciphers -v
Debug with SNI (Server Name Indication)
# Required for servers hosting multiple certificates
openssl s_client -connect host:443 -servername www.example.com
# Without SNI, you might get wrong certificate
openssl s_client -connect shared-host:443 # Wrong cert
openssl s_client -connect shared-host:443 -servername mysite.com # Correct
2. Certificate Inspection
Extract Certificate from Server
# One-liner to grab and save certificate
echo | openssl s_client -connect host:443 2>&1 | \
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > server.crt
# With timeout for unresponsive servers
echo | timeout 5 openssl s_client -connect host:443 2>&1 | \
sed -n '/BEGIN CERT/,/END CERT/p' > server.crt
# Get full chain (all certificates)
echo | openssl s_client -connect host:443 -showcerts 2>&1 | \
sed -n '/BEGIN CERT/,/END CERT/p' > chain.pem
Inspect Certificate Details
# Human-readable full output
openssl x509 -in cert.pem -text -noout
# Key fields only
openssl x509 -in cert.pem -noout \
-subject -issuer -dates -fingerprint
# Subject Alternative Names (SANs)
openssl x509 -in cert.pem -noout -text | grep -A1 "Subject Alternative Name"
# Check if wildcard
openssl x509 -in cert.pem -noout -subject | grep '\*'
Check Expiration
# Show expiry dates
openssl x509 -in cert.pem -dates -noout
# Check if expired (returns 0 if valid)
openssl x509 -in cert.pem -checkend 0
# Check if expiring in 30 days
openssl x509 -in cert.pem -checkend 2592000
# Script: Check multiple certificates
for cert in *.pem; do
echo -n "$cert: "
if openssl x509 -in "$cert" -checkend 2592000 -noout 2>/dev/null; then
echo "OK (valid > 30 days)"
else
openssl x509 -in "$cert" -enddate -noout
fi
done
Verify Certificate/Key Match
# These hashes MUST match for cert+key to work together
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5
# One-liner check
cert_hash=$(openssl x509 -noout -modulus -in cert.pem | md5sum | cut -d' ' -f1)
key_hash=$(openssl rsa -noout -modulus -in key.pem 2>/dev/null | md5sum | cut -d' ' -f1)
[[ "$cert_hash" == "$key_hash" ]] && echo "MATCH" || echo "MISMATCH"
3. Certificate Generation
Self-Signed Certificate (Quick)
# One-liner for testing
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 \
-nodes -keyout server.key -out server.crt \
-subj "/CN=myserver.local"
Self-Signed with SANs (Production)
# Modern browsers require SANs, not just CN
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 \
-nodes -keyout server.key -out server.crt \
-subj "/C=US/ST=CA/L=LA/O=MyOrg/CN=server.example.com" \
-addext "subjectAltName=DNS:server.example.com,DNS:*.server.example.com,IP:10.0.0.1" \
-addext "keyUsage=digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth"
Create CSR for CA Signing
# Generate key and CSR
openssl req -new -newkey rsa:4096 -nodes \
-keyout server.key -out server.csr \
-subj "/C=US/ST=California/L=Los Angeles/O=MyOrganization/OU=IT/CN=server.example.com"
# With SANs (requires config file or -addext)
openssl req -new -newkey rsa:4096 -nodes \
-keyout server.key -out server.csr \
-subj "/CN=server.example.com" \
-addext "subjectAltName=DNS:server.example.com,DNS:www.server.example.com"
# Verify CSR contents
openssl req -in server.csr -text -noout
Create Your Own CA
# Step 1: Generate CA private key
openssl genrsa -aes256 -out ca.key 4096
# Step 2: Generate CA certificate (10 years)
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
-out ca.crt \
-subj "/C=US/ST=CA/L=LA/O=MyOrg/OU=PKI/CN=MyOrg Root CA"
# Step 3: Sign server CSR with CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365 -sha256
# Step 4: Verify the signature
openssl verify -CAfile ca.crt server.crt
4. Format Conversion
Common Conversions
# PEM to DER
openssl x509 -in cert.pem -outform DER -out cert.der
# DER to PEM
openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem
# PEM to PKCS12 (for Windows/browsers)
openssl pkcs12 -export -out cert.p12 \
-inkey key.pem -in cert.pem -certfile ca.crt
# PKCS12 to PEM
openssl pkcs12 -in cert.p12 -out cert.pem -nodes
# PKCS7 to PEM
openssl pkcs7 -in cert.p7b -print_certs -out cert.pem
# Extract key from PKCS12
openssl pkcs12 -in cert.p12 -nocerts -nodes -out key.pem
# Extract cert from PKCS12
openssl pkcs12 -in cert.p12 -clcerts -nokeys -out cert.pem
File Format Reference
| Extension | Format | Contains | Use Case |
|---|---|---|---|
|
Base64 |
Cert and/or key |
Linux/Unix default |
|
Base64 |
Certificate only |
Common convention |
|
Binary (DER) or Base64 |
Certificate only |
Windows default |
|
Base64 |
Private key |
Key files |
|
Binary |
Certificate |
Java/Windows |
|
Binary PKCS12 |
Cert + key + chain |
Windows import |
|
PKCS7 |
Cert chain (no key) |
CA bundles |
|
Base64 |
Certificate request |
CA signing |
5. Troubleshooting Common Errors
Error: Self-Signed Certificate
verify error:num=18:self-signed certificate
Cause: Server presents self-signed certificate (no CA chain)
Solution for testing:
# Accept any certificate (TESTING ONLY)
curl -k https://host
openssl s_client -connect host:443 # Still connects, just warns
# Python
import ssl
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
Production solution: Import CA certificate to trust store
Error: Certificate Has Expired
verify error:num=10:certificate has expired
Check expiry:
echo | openssl s_client -connect host:443 2>&1 | openssl x509 -noout -dates
Solution: Renew the certificate
Error: Unable to Verify First Certificate
verify error:num=21:unable to verify the first certificate
Cause: Incomplete certificate chain
Debug:
echo | openssl s_client -connect host:443 -showcerts 2>&1 | grep -E "depth|verify"
Solution: Configure server to send intermediate certificates
Error: Hostname Mismatch
verify error:num=62:Hostname mismatch
Check certificate hostnames:
echo | openssl s_client -connect host:443 2>&1 | \
openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
Solution: Use correct hostname or get certificate with correct SANs
Error: Connection Reset by Peer
Connection reset by peer
Possible causes:
-
Wrong port
-
Service not running
-
Firewall blocking
-
TLS version mismatch
-
Client certificate required
Debug steps:
# Check if port is open
nc -zv host 443
# Try different TLS versions
openssl s_client -connect host:443 -tls1_2
openssl s_client -connect host:443 -tls1_3
# Check for client cert requirement
openssl s_client -connect host:443 2>&1 | grep -i "client"
6. Enterprise Integrations
Cisco ISE Certificate Inspection
# Admin GUI certificate (443)
echo | openssl s_client -connect ise.example.com:443 2>&1 | head -30
# ERS API certificate (9060)
echo | openssl s_client -connect ise.example.com:9060 2>&1 | head -30
# DataConnect (Oracle) certificate (2484)
echo | openssl s_client -connect ise.example.com:2484 2>&1 | head -30
# pxGrid certificate (8905)
echo | openssl s_client -connect ise.example.com:8905 2>&1 | head -30
7. Automation Scripts
Certificate Expiry Monitor
#!/bin/bash
# cert-monitor.sh - Check certificate expiry across hosts
HOSTS=(
"ise.example.com:443"
"ise.example.com:9060"
"pfsense.local:443"
"web.example.com:443"
)
WARN_DAYS=30
WARN_SECONDS=$((WARN_DAYS * 86400))
for hostport in "${HOSTS[@]}"; do
cert=$(echo | timeout 5 openssl s_client -connect "$hostport" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p')
if [[ -z "$cert" ]]; then
echo "[$hostport] ERROR: Could not retrieve certificate"
continue
fi
expiry=$(echo "$cert" | openssl x509 -noout -enddate | cut -d= -f2)
if echo "$cert" | openssl x509 -checkend $WARN_SECONDS -noout 2>/dev/null; then
echo "[$hostport] OK - Expires: $expiry"
else
echo "[$hostport] WARNING - Expires: $expiry (< $WARN_DAYS days)"
fi
done
Bulk Certificate Extraction
#!/bin/bash
# extract-certs.sh - Extract certificates from multiple hosts
HOSTS="$1" # File with host:port per line
OUTDIR="${2:-./certs}"
mkdir -p "$OUTDIR"
while read -r hostport; do
[[ -z "$hostport" || "$hostport" =~ ^# ]] && continue
name=$(echo "$hostport" | tr ':' '_')
echo "Extracting: $hostport"
echo | timeout 5 openssl s_client -connect "$hostport" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$OUTDIR/$name.pem"
if [[ -s "$OUTDIR/$name.pem" ]]; then
echo " -> $OUTDIR/$name.pem"
openssl x509 -in "$OUTDIR/$name.pem" -noout -subject -dates
else
echo " -> FAILED"
rm -f "$OUTDIR/$name.pem"
fi
done < "$HOSTS"
8. Security Best Practices
Certificate Validation
Always validate in production:
# Verify chain against system CA store
openssl s_client -connect host:443 -CApath /etc/ssl/certs
# Verify against specific CA
openssl verify -CAfile /path/to/ca.crt server.crt
9. ISE Certificate Extraction & Installation
Extract Certificates from ISE
DOMAIN="<domain>"
ISE_HOST="<ise-ip-or-fqdn>"
CERT_DIR="$HOME/.secrets/certs/$DOMAIN/ise"
mkdir -p "$CERT_DIR"
# ROOT-CA cert (port 443) - Admin/ERS/MnT/OpenAPI
# NOTE: Use -showcerts and extract the LAST cert (root CA), not the first (server cert)
echo | openssl s_client -connect "$ISE_HOST:443" -showcerts 2>&1 | \
awk '/-----BEGIN CERTIFICATE-----/{buf=""} {buf=buf $0 ORS} /-----END CERTIFICATE-----/{last=buf} END{printf "%s", last}' > "$CERT_DIR/ROOT-CA.crt"
# DataConnect cert (port 2484 - Oracle TCPS)
echo | openssl s_client -connect "$ISE_HOST:2484" 2>&1 | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/dataconnect.crt"
# pxGrid cert (port 8910)
echo | openssl s_client -connect "$ISE_HOST:8910" 2>&1 | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/pxgrid.crt"
chmod 600 "$CERT_DIR"/*.crt
Verify Certificate Before Installing
# Check issuer and validity
openssl x509 -in ~/.secrets/certs/<domain>/ise/ROOT-CA.crt -noout -issuer -subject -dates
openssl x509 -in ~/.secrets/certs/<domain>/ise/dataconnect.crt -noout -issuer -subject -dates
# Check fingerprint
openssl x509 -in ~/.secrets/certs/<domain>/ise/dataconnect.crt -noout -fingerprint -sha256
Install Certificate
Option 1: System trust store (Arch Linux)
sudo cp ~/.secrets/certs/<domain>/ise/dataconnect.crt /etc/ca-certificates/trust-source/anchors/
sudo update-ca-trust
Option 2: System trust store (Debian/Ubuntu)
sudo cp ~/.secrets/certs/<domain>/ise/dataconnect.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
Option 3: netapi only (env var) - Recommended
Add to your network.env:
ISE_CA_CERT=~/.secrets/certs/<domain>/ise/ROOT-CA.crt
ISE_DATACONNECT_CA=~/.secrets/certs/<domain>/ise/dataconnect.crt
ISE_PXGRID_CA=~/.secrets/certs/<domain>/ise/pxgrid.crt
10. Certificate Storage for Programmatic Access
Directory Structure
Store CA certificates for programmatic access under ~/.secrets/certs/<domain>/<service>/:
~/.secrets/certs/ ├── d000/ # Home enterprise domain │ ├── ise/ # Cisco ISE service │ │ ├── ROOT-CA.crt # Admin/ERS/MnT/OpenAPI (port 443, 9060) │ │ ├── dataconnect.crt # Oracle TCPS (port 2484) │ │ └── pxgrid.crt # pxGrid controller (port 8910) │ ├── pfsense/ │ │ └── api.crt # pfSense API │ └── ldap/ │ └── dc01.crt # Domain controller LDAPS ├── d001/ # Work domain │ ├── ise/ │ │ ├── ROOT-CA.crt │ │ ├── dataconnect.crt │ │ └── pxgrid.crt │ └── ldap/ │ ├── dc01.crt │ └── dc02.crt └── README.md # Documentation
Naming convention: ~/.secrets/certs/<domain>/<service>/<name>.crt
-
domain- Environment identifier (d000=home, d001=work, etc.) -
service- Service category (ise, pfsense, ldap, etc.) -
name- Specific certificate (dataconnect, ers, admin, etc.)
Step-by-Step Setup (Copy-Paste)
Copy-paste each command one at a time.
Step 1: Set variables
DOMAIN="<your-domain>" # e.g., d000, d001
ISE_HOST="<ise-ip-or-fqdn>" # e.g., 10.50.1.21, ise.example.com
CERT_DIR="$HOME/.secrets/certs/$DOMAIN/ise"
Step 2: Create directory
mkdir -p "$CERT_DIR"
chmod 700 "$CERT_DIR"
Step 3: Extract ROOT-CA cert (port 443)
Used by Admin GUI, ERS, MnT, OpenAPI. NOTE: The first cert is ISE’s server cert. We need the LAST cert (root CA) from the chain.
echo | timeout 5 openssl s_client -connect "$ISE_HOST:443" -showcerts 2>/dev/null | \
awk '/-----BEGIN CERTIFICATE-----/{buf=""} {buf=buf $0 ORS} /-----END CERTIFICATE-----/{last=buf} END{printf "%s", last}' > "$CERT_DIR/ROOT-CA.crt"
Step 4: Verify ROOT-CA cert
openssl x509 -in "$CERT_DIR/ROOT-CA.crt" -noout -subject -dates
Step 5: Extract DataConnect cert (port 2484)
Self-signed Oracle cert for DataConnect.
echo | timeout 5 openssl s_client -connect "$ISE_HOST:2484" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/dataconnect.crt"
Step 6: Verify DataConnect cert
openssl x509 -in "$CERT_DIR/dataconnect.crt" -noout -subject -dates
Step 7: Extract pxGrid cert (port 8910)
pxGrid controller certificate.
echo | timeout 5 openssl s_client -connect "$ISE_HOST:8910" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/pxgrid.crt"
Step 8: Verify pxGrid cert
openssl x509 -in "$CERT_DIR/pxgrid.crt" -noout -subject -dates
Step 9: Set permissions
chmod 600 "$CERT_DIR"/*.crt
ls -la "$CERT_DIR"
Step 10: Update network.env
Add these lines to your domain’s network.env (replace <domain>):
ISE_CA_CERT=~/.secrets/certs/<domain>/ise/ROOT-CA.crt
ISE_DATACONNECT_CA=~/.secrets/certs/<domain>/ise/dataconnect.crt
ISE_PXGRID_CA=~/.secrets/certs/<domain>/ise/pxgrid.crt
Automated Setup Script
#!/bin/bash
# setup-ise-certs.sh - Extract and store ISE certificates for a domain
#
# Usage:
# setup-ise-certs.sh <domain> <ise_host> # Run all steps automatically
# setup-ise-certs.sh -i <domain> <ise_host> # Interactive mode (step-by-step)
# Parse flags
INTERACTIVE=false
if [[ "$1" == "-i" ]]; then
INTERACTIVE=true
shift
fi
DOMAIN="${1:?Usage: setup-ise-certs.sh [-i] <domain> <ise_host>}"
ISE_HOST="${2:?Usage: setup-ise-certs.sh [-i] <domain> <ise_host>}"
CERT_DIR="$HOME/.secrets/certs/$DOMAIN/ise"
# Helper for interactive mode
confirm() {
if $INTERACTIVE; then
echo
read -p "$1 [Y/n] " -n 1 -r
echo
[[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]
else
return 0
fi
}
echo "=============================================="
echo " ISE Certificate Setup - $DOMAIN"
echo " Host: $ISE_HOST"
echo " Mode: $($INTERACTIVE && echo 'Interactive' || echo 'Automatic')"
echo "=============================================="
echo
# Step 1: Create directory
echo "[Step 1] Create certificate directory"
echo " Path: $CERT_DIR"
if confirm "Create directory?"; then
mkdir -p "$CERT_DIR"
chmod 700 "$CERT_DIR"
echo " Done"
else
echo " Skipped"
fi
# Step 2: Extract ROOT-CA cert
echo
echo "[Step 2] Extract ROOT-CA certificate (port 443)"
echo " Used by: Admin GUI, ERS API (9060), MnT API, OpenAPI"
echo " Note: Extracts the LAST cert in chain (root CA), not the server cert"
if confirm "Extract ROOT-CA.crt?"; then
echo -n " Connecting to $ISE_HOST:443... "
if echo | timeout 5 openssl s_client -connect "$ISE_HOST:443" -showcerts 2>/dev/null | \
awk '/-----BEGIN CERTIFICATE-----/{buf=""} {buf=buf $0 ORS} /-----END CERTIFICATE-----/{last=buf} END{printf "%s", last}' > "$CERT_DIR/ROOT-CA.crt" && \
[ -s "$CERT_DIR/ROOT-CA.crt" ]; then
echo "OK"
echo " Certificate details:"
openssl x509 -in "$CERT_DIR/ROOT-CA.crt" -noout -subject -issuer -dates 2>/dev/null | sed 's/^/ /'
echo " Fingerprint:"
openssl x509 -in "$CERT_DIR/ROOT-CA.crt" -noout -fingerprint -sha256 2>/dev/null | sed 's/^/ /'
else
echo "FAILED"
rm -f "$CERT_DIR/ROOT-CA.crt"
fi
else
echo " Skipped"
fi
# Step 3: Extract DataConnect cert
echo
echo "[Step 3] Extract DataConnect certificate (port 2484)"
echo " Used by: ISE DataConnect (Oracle TCPS)"
echo " Note: This is a separate self-signed Oracle certificate"
if confirm "Extract dataconnect.crt?"; then
echo -n " Connecting to $ISE_HOST:2484... "
if echo | timeout 5 openssl s_client -connect "$ISE_HOST:2484" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/dataconnect.crt" && \
[ -s "$CERT_DIR/dataconnect.crt" ]; then
echo "OK"
echo " Certificate details:"
openssl x509 -in "$CERT_DIR/dataconnect.crt" -noout -subject -issuer -dates 2>/dev/null | sed 's/^/ /'
echo " Fingerprint:"
openssl x509 -in "$CERT_DIR/dataconnect.crt" -noout -fingerprint -sha256 2>/dev/null | sed 's/^/ /'
else
echo "FAILED (DataConnect may not be enabled)"
rm -f "$CERT_DIR/dataconnect.crt"
fi
else
echo " Skipped"
fi
# Step 4: Extract pxGrid cert
echo
echo "[Step 4] Extract pxGrid certificate (port 8910)"
echo " Used by: pxGrid controller"
if confirm "Extract pxgrid.crt?"; then
echo -n " Connecting to $ISE_HOST:8910... "
if echo | timeout 5 openssl s_client -connect "$ISE_HOST:8910" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/pxgrid.crt" && \
[ -s "$CERT_DIR/pxgrid.crt" ]; then
echo "OK"
echo " Certificate details:"
openssl x509 -in "$CERT_DIR/pxgrid.crt" -noout -subject -issuer -dates 2>/dev/null | sed 's/^/ /'
echo " Fingerprint:"
openssl x509 -in "$CERT_DIR/pxgrid.crt" -noout -fingerprint -sha256 2>/dev/null | sed 's/^/ /'
else
echo "FAILED (pxGrid may not be enabled)"
rm -f "$CERT_DIR/pxgrid.crt"
fi
else
echo " Skipped"
fi
# Step 5: Set permissions
echo
echo "[Step 5] Set file permissions"
if confirm "Set permissions (chmod 600)?"; then
chmod 600 "$CERT_DIR"/*.crt 2>/dev/null
echo " Done"
else
echo " Skipped"
fi
# Summary
echo
echo "=============================================="
echo " Summary"
echo "=============================================="
echo "Certificates in $CERT_DIR:"
ls -la "$CERT_DIR"/*.crt 2>/dev/null || echo " (none)"
echo
echo "Add to your network.env:"
echo " ISE_CA_CERT=~/.secrets/certs/$DOMAIN/ise/ROOT-CA.crt"
echo " ISE_DATACONNECT_CA=~/.secrets/certs/$DOMAIN/ise/dataconnect.crt"
echo " ISE_PXGRID_CA=~/.secrets/certs/$DOMAIN/ise/pxgrid.crt"
Integration with netapi
Add certificate paths to your domain’s network.env:
# ~/.secrets/environments/domains/<domain>/dev/network.env
# ISE Connection Settings
ISE_PAN_IP=10.50.1.20
ISE_MNT_IP=10.50.1.21
ISE_API_USER=ersadmin
ISE_API_PASS=<encrypted>
# Certificate Paths (enables proper SSL verification)
# ISE_CA_CERT: For Admin/ERS/MnT APIs (ROOT-CA cert)
# ISE_DATACONNECT_CA: For DataConnect (separate Oracle self-signed cert)
# ISE_PXGRID_CA: For pxGrid controller
ISE_CA_CERT=~/.secrets/certs/<domain>/ise/ROOT-CA.crt
ISE_DATACONNECT_CA=~/.secrets/certs/<domain>/ise/dataconnect.crt
ISE_PXGRID_CA=~/.secrets/certs/<domain>/ise/pxgrid.crt
How netapi Uses Certificates
For ERS/MnT/OpenAPI (netapi ise get-endpoints, netapi ise mnt sessions, etc.):
-
ISE_CA_CERT→ CA or admin cert for server verification -
Falls back to
ISE_MTLS_CAif set (for mutual TLS environments)
For DataConnect (netapi ise dc test, netapi ise dc sessions, etc.):
-
ISE_DATACONNECT_CA→ DataConnect’s self-signed Oracle cert -
Does NOT fall back to
ISE_CA_CERT(different certificate)
When CA certificate is configured:
-
Loads certificate from specified path
-
Enables proper SSL verification (
CERT_REQUIRED) -
Connection validates against the CA cert
When CA certificate is NOT set:
-
INSECURE=true→ Skips all SSL verification silently -
Otherwise → Interactive prompt with options (y/n/s/c)
Interactive SSL Fallback
When SSL verification fails, netapi provides an interactive prompt:
$ netapi ise dc test SSL verification failed for 10.50.1.21:2484 DPY-6005: cannot connect to database Subject: O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev Options: y - Proceed insecurely (this time only) n - Abort (default) s - Save INSECURE=true preference c - Extract certificate and save to ~/.secrets/certs/ Choice [y/n/s/c]: c Certificate saved: /home/user/.secrets/certs/d000/ise/dataconnect.crt Subject: O=Cisco Systems, CN=ISE_ORACLE_ise-02.inside.domusdigitalis.dev Expires: Jan 13 02:01:10 2027 GMT Add to your network.env: ISE_DATACONNECT_CA=/home/user/.secrets/certs/d000/ise/dataconnect.crt Retrying with certificate verification... ✓ Connected to ISE DataConnect (10.50.1.21:2484)
Verify Certificate Before Trusting
Always inspect certificates before adding to trust:
# View certificate details
openssl x509 -in ~/.secrets/certs/d000/ise/dataconnect.crt -text -noout | head -30
# Check fingerprint matches what you expect
openssl x509 -in ~/.secrets/certs/d000/ise/dataconnect.crt -noout -fingerprint -sha256
# Compare with live server
echo | openssl s_client -connect 10.50.1.21:2484 2>&1 | \
openssl x509 -noout -fingerprint -sha256
Certificate Renewal Workflow
When ISE certificates are renewed:
#!/bin/bash
# renew-ise-certs.sh - Update stored certificates after ISE renewal
DOMAIN="${1:-d000}"
ISE_HOST="${2:-10.50.1.21}"
CERT_DIR="$HOME/.secrets/certs/$DOMAIN/ise"
echo "=== Renewing ISE certificates for $DOMAIN ==="
# Backup existing certs
mkdir -p "$CERT_DIR/backup"
cp "$CERT_DIR"/*.crt "$CERT_DIR/backup/" 2>/dev/null
# Extract new certs (admin cert covers ERS/MnT/OpenAPI, dataconnect is separate)
for port_name in "443:admin" "2484:dataconnect"; do
port="${port_name%%:*}"
name="${port_name##*:}"
echo -n "Extracting $name (port $port)... "
if echo | timeout 5 openssl s_client -connect "$ISE_HOST:$port" 2>/dev/null | \
sed -n '/BEGIN CERT/,/END CERT/p' > "$CERT_DIR/$name.crt.new" && \
[ -s "$CERT_DIR/$name.crt.new" ]; then
# Compare old and new
if [ -f "$CERT_DIR/$name.crt" ]; then
old_fp=$(openssl x509 -in "$CERT_DIR/$name.crt" -noout -fingerprint -sha256 2>/dev/null)
new_fp=$(openssl x509 -in "$CERT_DIR/$name.crt.new" -noout -fingerprint -sha256)
if [ "$old_fp" = "$new_fp" ]; then
echo "unchanged"
rm "$CERT_DIR/$name.crt.new"
else
echo "UPDATED"
mv "$CERT_DIR/$name.crt.new" "$CERT_DIR/$name.crt"
echo " Old: $old_fp"
echo " New: $new_fp"
fi
else
mv "$CERT_DIR/$name.crt.new" "$CERT_DIR/$name.crt"
echo "created"
fi
else
echo "FAILED"
rm -f "$CERT_DIR/$name.crt.new"
fi
done
echo
echo "Certificates in $CERT_DIR:"
ls -la "$CERT_DIR"/*.crt 2>/dev/null
Related Documents
-
PRJ-SECRETS: Service Certificates - Full Antora documentation with diagrams
-
Netcat Operations - Network debugging companion
-
Password Generation - Secure credential management
-
Network Troubleshooting - Broader network debugging
Certificate mastery is essential for modern security operations. Practice these commands until they’re muscle memory.