Skip to content

Thumbprint Mode

Thumbprint mode enables mTLS authentication using self-signed certificates verified by their SHA-256 fingerprint.

ScenarioWhy Thumbprint Mode
Quick setupNo CA infrastructure needed
Small deploymentsManual management is feasible
DevelopmentSimple to configure
Isolated networksNo external CA dependencies
POC/testingMinimal setup time
AspectThumbprintCA-Signed
Setup complexityLowMedium
CA requiredNoYes
ScalabilityManual per-agentAutomated
Certificate managementPer-agentCentralized
Best forSmall deploymentsEnterprise
[tls]
auth_mode = "thumbprint"
# Server certificate
cert_path = "/etc/mantis/certs/server-cert.pem"
key_path = "/etc/mantis/certs/server-key.pem"
# No CA cert needed for thumbprint mode
# But can still be provided for server cert chain
Terminal window
# Enable thumbprint mode
export MANTIS_TLS_AUTH_MODE=thumbprint
export MANTIS_TLS_CERT_PATH=/etc/mantis/certs/server-cert.pem
export MANTIS_TLS_KEY_PATH=/etc/mantis/certs/server-key.pem
[tls]
cert_path = "/etc/mantis/certs/tarsus-cert.pem"
key_path = "/etc/mantis/certs/tarsus-key.pem"
# Thorax's server certificate thumbprint (SHA-256, 64 hex chars).
# Required in thumbprint mode: Tarsus verifies the Thorax server cert by
# its fingerprint rather than a CA chain (Thorax presents a self-signed cert).
trust_server_thumbprint = "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
# CA certificate used to verify the Thorax server and, in listen mode, to
# enforce mTLS on inbound connections. Required in all modes — without it
# Tarsus refuses to start.
ca_cert_path = "/etc/mantis/certs/ca-cert.pem"

Tarsus automatically generates a self-signed certificate on first run if one is not configured, and mantisctl cert generate-server/generate-client produce correctly-shaped certs (right EKUs and SANs) when you need to pre-generate one. Prefer those over hand-rolled OpenSSL.

Only if the shipped tooling is unavailable.

The certificate must carry both clientAuth and serverAuth, plus a SAN for the hostname Thorax dials — in listen mode Thorax connects to the agent, so the agent presents this certificate as a server. A clientAuth-only certificate is rejected with UnsupportedCertificate on the first listen-mode connection.

Terminal window
cat > /tmp/agent-ext.cnf <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = DNS:web-prod-01.example.com
EOF
openssl req -new -x509 -nodes -newkey rsa:2048 \
-keyout /etc/mantis/certs/tarsus-key.pem \
-out /etc/mantis/certs/tarsus-cert.pem \
-days 365 -sha256 \
-subj "/CN=$(hostname)/O=Mantis Agent" \
-extensions v3_req -config <(cat /etc/ssl/openssl.cnf /tmp/agent-ext.cnf)
systemctl restart tarsus@<instance>

Restarting is required — Tarsus reads its certificate once at startup and does not watch the file or handle SIGHUP.

ParameterRecommended Value
Key size2048 bits (RSA) or P-256 (ECDSA)
Validity365 days
CNHostname or agent name
Extended Key UsageclientAuth, serverAuth
Subject Alt NameDNS name Thorax dials (listen mode)
SignatureSHA-256

mantisctl cert generate-server --name <agent> --sans <hostname> produces a certificate with these properties without the OpenSSL config dance.

Terminal window
# Get thumbprint from certificate
mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
# Output:
# abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
# Using OpenSSL
openssl x509 -in /etc/mantis/certs/tarsus-cert.pem -fingerprint -sha256 -noout | \
sed 's/SHA256 Fingerprint=//' | tr -d ':' | tr '[:upper:]' '[:lower:]'
FormatExample
Mantisabcdef1234567890abcdef1234567890... (64 chars)
OpenSSLAB:CD:EF:12:34:56:78:90:... (colon-separated)

Convert between formats:

Terminal window
# OpenSSL to Mantis format
echo "AB:CD:EF:12:..." | tr -d ':' | tr '[:upper:]' '[:lower:]'
# Mantis to OpenSSL format (for display)
echo "abcdef12..." | sed 's/../&:/g' | sed 's/:$//' | tr '[:lower:]' '[:upper:]'

Register thumbprint before agent connects:

Terminal window
# 1. On agent: get thumbprint
mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
# abcdef1234567890...
# 2. Share thumbprint securely with admin
# (phone, encrypted email, secure chat)
# 3. Admin pre-registers thumbprint
mantisctl cert pre-register \
--name "web-prod-01" \
--thumbprint "abcdef1234567890..."
# 4. Agent connects and is auto-approved
tarsus run

Approve after agent connects:

Terminal window
# 1. Agent connects (no pre-registration)
tarsus run
# Status: Pending (awaiting approval)
# 2. Admin sees pending registration
mantisctl cert list --status pending
# CLIENT THUMBPRINT HOSTNAME
# unknown-01 xyz789... server.local
# 3. Admin verifies and approves (by registration ID or thumbprint prefix)
mantisctl cert approve "<REGISTRATION_UUID>" \
--notes "Verified web-prod-01 out of band"
# 4. Agent is now authenticated
┌─────────────────────────────────────────────────────────────┐
│ Pending Registrations │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┬───────────────┬─────────────────────┐ │
│ │ Client │ Thumbprint │ Actions │ │
│ ├────────────────┼───────────────┼─────────────────────┤ │
│ │ unknown-01 │ xyz789... │ [Approve] [Reject] │ │
│ │ unknown-02 │ abc123... │ [Approve] [Reject] │ │
│ └────────────────┴───────────────┴─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Always verify thumbprints through a secure channel:

ChannelSecurity LevelUse Case
In-personHighestHigh-security
Phone callHighVerbal confirmation
Encrypted emailMediumAudit trail
Secure chatMediumQuick verification
Terminal window
# Secure key file permissions
chmod 600 /etc/mantis/certs/tarsus-key.pem
chown root:root /etc/mantis/certs/tarsus-key.pem
# Verify
ls -la /etc/mantis/certs/tarsus-key.pem
# -rw------- 1 root root 1679 Jan 15 10:00 /etc/mantis/certs/tarsus-key.pem

Self-signed certificates should be renewed before expiry:

Terminal window
# Check expiration
openssl x509 -in /etc/mantis/certs/tarsus-cert.pem -enddate -noout
# notAfter=Jan 15 10:00:00 2026 GMT
# Generate new certificate using OpenSSL
openssl req -new -x509 -nodes \
-keyout /etc/mantis/certs/tarsus-key.pem \
-out /etc/mantis/certs/tarsus-cert.pem \
-days 365 \
-subj "/CN=$(hostname)/O=Mantis Agent"
# Get new thumbprint
mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
# Re-register with the new thumbprint (revoke old, pre-register new — there is no
# in-place "update thumbprint" verb)
mantisctl cert revoke "$OLD_REGISTRATION_ID" --reason "thumbprint rotation"
mantisctl cert pre-register --name "web-prod-01" --thumbprint "$(mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem)"

For deploying multiple agents:

deploy-agents.sh
#!/bin/bash
SERVERS="web-01 web-02 api-01 api-02"
for server in $SERVERS; do
# Get thumbprint from server (assumes SSH access)
thumbprint=$(ssh $server "mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem")
# Pre-register in Mantis
mantisctl cert pre-register \
--name "$server" \
--thumbprint "$thumbprint"
echo "Registered: $server"
done

Ansible example:

- name: Get Tarsus thumbprint
command: mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
register: thumbprint
- name: Register with Mantis
uri:
url: '{{ mantis_api_url }}/api/v1/registrations/pre-register'
method: POST
headers:
Authorization: 'Bearer {{ mantis_token }}'
body_format: json
body:
client_name: '{{ inventory_hostname }}'
thumbprint: '{{ thumbprint.stdout }}'
tenant_id: '{{ tenant_id }}'

Problem: Agent shows “Connecting…” but never authenticates

Diagnosis:

Terminal window
# Check agent logs
journalctl -u tarsus@<instance> -f
# Verify certificate
openssl x509 -in /etc/mantis/certs/tarsus-cert.pem -text -noout
# Test connection
openssl s_client -connect thorax.example.com:50051 \
-cert /etc/mantis/certs/tarsus-cert.pem \
-key /etc/mantis/certs/tarsus-key.pem

Problem: Agent rejected with “thumbprint mismatch”

Diagnosis:

Terminal window
# Get actual thumbprint from agent
mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
# Compare with the registered thumbprint (by registration ID or thumbprint prefix)
mantisctl cert show "agent-registration-id"
# If different, certificate was regenerated

Solution:

Terminal window
# Re-register with the current thumbprint (revoke old, pre-register new)
mantisctl cert revoke "$OLD_REGISTRATION_ID" --reason "thumbprint rotation"
mantisctl cert pre-register --name "agent-name" \
--thumbprint "$(ssh agent-server 'mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem')"

Problem: Agent rejected with “certificate expired”

Solution:

Terminal window
# On agent: regenerate certificate using OpenSSL
openssl req -new -x509 -nodes \
-keyout /etc/mantis/certs/tarsus-key.pem \
-out /etc/mantis/certs/tarsus-cert.pem \
-days 365 \
-subj "/CN=$(hostname)/O=Mantis Agent"
# Get new thumbprint
mantisctl cert thumbprint /etc/mantis/certs/tarsus-cert.pem
# Re-register with the new thumbprint (revoke old, pre-register new)
mantisctl cert revoke "$OLD_REGISTRATION_ID" --reason "certificate renewal"
mantisctl cert pre-register --name "agent-name" \
--thumbprint "new-thumbprint-here"
# Restart agent
systemctl restart tarsus@<instance>
ErrorCauseSolution
no certificate presentedTLS config wrongCheck cert_path path
thumbprint not foundNot registeredPre-register or approve
registration pendingAwaiting approvalApprove in Mantis
registration revokedAgent was revokedRe-register
certificate expiredCert past validityRegenerate certificate

When ready to migrate from thumbprint to CA-signed mode:

  1. Deploy CA infrastructure (see CA-Signed Mode)
  2. Issue CA-signed certificates to agents
  3. Update Thorax configuration to auth_mode = "ca_signed"
  4. Agents re-register with new certificates

Pre-registration is more secure than post-connection approval:

  • Reduces window of vulnerability
  • Ensures only expected agents connect
  • Creates audit trail before deployment
Terminal window
# Good: descriptive names
mantisctl cert pre-register --name "web-prod-01" --thumbprint "..."
mantisctl cert pre-register --name "api-staging-02" --thumbprint "..."
# Bad: generic names
mantisctl cert pre-register --name "server1" --thumbprint "..."
mantisctl cert pre-register --name "agent" --thumbprint "..."

Maintain records of:

  • Who requested the registration
  • Purpose of the agent
  • Expected thumbprint value
  • Verification method used
Terminal window
# List all registrations
mantisctl cert list
# Review pending approvals
mantisctl cert list --status pending