Initial commit: DashCaddy v1.0
Full codebase including API server (32 modules + routes), dashboard frontend, DashCA certificate distribution, installer script, and deployment skills.
This commit is contained in:
281
ca/README.md
Normal file
281
ca/README.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# DashCA - Certificate Authority Distribution
|
||||
|
||||
A self-hosted landing page for distributing your root CA certificate with one-click installation across all major platforms.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Regenerate All Certificate Formats
|
||||
|
||||
```bash
|
||||
cd scripts
|
||||
bash generate-all.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Copy root.crt and intermediate.crt from Caddy PKI
|
||||
2. Generate root.der (DER format for Windows)
|
||||
3. Generate root.mobileconfig (Apple profile for iOS/macOS)
|
||||
4. Extract certificate metadata to cert-info.json
|
||||
|
||||
### Deploy to Production
|
||||
|
||||
```bash
|
||||
# Copy all files to production directory
|
||||
cp -r e:/CaddyCerts/sites/ca/* C:/caddy/sites/ca/
|
||||
```
|
||||
|
||||
Or deploy via the dashboard app selector (preferred method).
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
ca/
|
||||
├── index.html # Landing page with OS detection
|
||||
├── root.crt # Root CA certificate (PEM format)
|
||||
├── root.der # Root CA certificate (DER format)
|
||||
├── root.mobileconfig # Apple configuration profile
|
||||
├── intermediate.crt # Intermediate CA certificate
|
||||
├── cert-info.json # Certificate metadata (auto-generated)
|
||||
├── scripts/
|
||||
│ ├── install.ps1 # Windows PowerShell installer
|
||||
│ ├── install.sh # Linux/macOS shell installer
|
||||
│ ├── generate-cert-info.js # Extract certificate metadata
|
||||
│ ├── generate-mobileconfig.js # Generate Apple profile
|
||||
│ └── generate-all.sh # Wrapper script to regenerate all
|
||||
└── assets/
|
||||
└── (icons, logos, etc.)
|
||||
```
|
||||
|
||||
## Certificate Information
|
||||
|
||||
**Source:** Caddy's built-in PKI at `C:/caddy/certs/pki/authorities/local/`
|
||||
|
||||
- **Name:** Sami Home Network Root CA
|
||||
- **Algorithm:** ECDSA P-256 with SHA-256
|
||||
- **Valid Until:** Dec 22, 2034
|
||||
- **Fingerprint:** `08:98:A5:63:F5:A1:A2:58:5F:02:D7:A8:A2:54:87:E6:BC:33:96:21:29:0E`
|
||||
|
||||
## Installation Scripts
|
||||
|
||||
### Windows (install.ps1)
|
||||
|
||||
Features:
|
||||
- Requires Administrator privileges
|
||||
- Downloads certificate from ca.sami
|
||||
- Verifies SHA-256 fingerprint
|
||||
- Installs to LocalMachine\Root store
|
||||
- Checks for existing installation
|
||||
|
||||
**One-liner:**
|
||||
```powershell
|
||||
irm https://ca.sami/install.ps1 | iex
|
||||
```
|
||||
|
||||
### Linux/macOS (install.sh)
|
||||
|
||||
Features:
|
||||
- Requires sudo/root
|
||||
- Auto-detects OS (Debian, RedHat, Arch, macOS)
|
||||
- Platform-specific installation commands
|
||||
- Fingerprint verification with OpenSSL
|
||||
- Checks for existing installation
|
||||
|
||||
**One-liner:**
|
||||
```bash
|
||||
curl -fsSL https://ca.sami/install.sh | sudo bash
|
||||
```
|
||||
|
||||
### Apple Devices (root.mobileconfig)
|
||||
|
||||
Features:
|
||||
- Works on both iOS and macOS
|
||||
- XML configuration profile format
|
||||
- Contains base64-encoded certificate
|
||||
- Unique UUIDs per generation
|
||||
- User must manually trust after installation (iOS)
|
||||
|
||||
**Installation:**
|
||||
1. Download root.mobileconfig
|
||||
2. iOS: Settings prompts automatically
|
||||
3. macOS: System Settings → Profiles → Install
|
||||
4. iOS: Enable trust in Certificate Trust Settings
|
||||
|
||||
## Landing Page Features
|
||||
|
||||
The landing page (`index.html`) includes:
|
||||
|
||||
- **OS Detection:** Automatically detects Windows, macOS, Linux, iOS, Android
|
||||
- **Certificate Info Display:** Shows name, fingerprint, expiration, algorithm
|
||||
- **QR Code:** For easy mobile access (powered by qrcodejs library)
|
||||
- **Download Links:** All certificate formats and installation scripts
|
||||
- **Platform Tabs:** Detailed instructions for each operating system
|
||||
- **Copy-to-Clipboard:** For fingerprint and command-line scripts
|
||||
- **DashCaddy Theme:** Dark mode with Sami Grotesk font
|
||||
|
||||
**API Integration:**
|
||||
- Loads certificate info from `/api/ca/info` endpoint
|
||||
- Falls back to static info if API unavailable
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. **Edit Files:** Make changes in `e:/CaddyCerts/sites/ca/`
|
||||
2. **Test Locally:** Open `index.html` in browser (file:// protocol works)
|
||||
3. **Regenerate Certificates:** Run `scripts/generate-all.sh` if CA renewed
|
||||
4. **Deploy:** Copy to production or use dashboard deployment
|
||||
5. **Verify:** Visit https://ca.sami and test on target platforms
|
||||
|
||||
## Updating After CA Renewal
|
||||
|
||||
When Caddy regenerates its CA certificate (every ~10 years):
|
||||
|
||||
### 1. Regenerate Certificate Formats
|
||||
|
||||
```bash
|
||||
cd e:/CaddyCerts/sites/ca/scripts
|
||||
bash generate-all.sh
|
||||
```
|
||||
|
||||
### 2. Update Fingerprints in Scripts
|
||||
|
||||
The new fingerprint will be in `cert-info.json`. Update these files:
|
||||
|
||||
**install.ps1** (line 17):
|
||||
```powershell
|
||||
$ExpectedFingerprint = "NEW:FIN:GER:PRINT:HERE"
|
||||
```
|
||||
|
||||
**install.sh** (line 13):
|
||||
```bash
|
||||
EXPECTED_FP="NEW:FIN:GER:PRINT:HERE"
|
||||
```
|
||||
|
||||
### 3. Deploy to Production
|
||||
|
||||
```bash
|
||||
cp -r e:/CaddyCerts/sites/ca/* C:/caddy/sites/ca/
|
||||
```
|
||||
|
||||
### 4. Notify Users
|
||||
|
||||
- Add banner to dashboard
|
||||
- Send notification via configured channels
|
||||
- Update documentation with new expiration date
|
||||
|
||||
## API Endpoints
|
||||
|
||||
DashCA integrates with DashCaddy API:
|
||||
|
||||
### GET /api/ca/info
|
||||
|
||||
Returns certificate metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"certificate": {
|
||||
"name": "Sami Home Network Root CA",
|
||||
"fingerprint": "08:98:A5:...",
|
||||
"validFrom": "Feb 12 07:44:51 2025 GMT",
|
||||
"validUntil": "Dec 22 07:44:51 2034 GMT",
|
||||
"daysUntilExpiration": 3235,
|
||||
"algorithm": "ECDSA P-256 with SHA-256",
|
||||
"serialNumber": "c1:dc:48:...",
|
||||
"downloadUrl": "https://ca.sami/root.crt"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/health/ca
|
||||
|
||||
Returns CA expiration health status:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"message": "CA certificate valid for 3235 days",
|
||||
"daysUntilExpiration": 3235,
|
||||
"expiresAt": "Dec 22 07:44:51 2034 GMT"
|
||||
}
|
||||
```
|
||||
|
||||
**Status values:**
|
||||
- `healthy`: >90 days remaining
|
||||
- `warning`: 30-90 days
|
||||
- `critical`: <30 days or expired
|
||||
- `error`: Certificate not found or error reading
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Certificate Not Found Error
|
||||
|
||||
**Symptom:** Scripts fail with "certificate not found"
|
||||
**Cause:** Caddy hasn't generated the local CA yet
|
||||
**Solution:** Visit any *.sami domain to trigger CA generation
|
||||
|
||||
### Fingerprint Mismatch
|
||||
|
||||
**Symptom:** Install scripts reject certificate with fingerprint mismatch
|
||||
**Cause:** CA was renewed but scripts not updated
|
||||
**Solution:** Run `generate-all.sh` and update fingerprints in install scripts
|
||||
|
||||
### iOS Profile Won't Install
|
||||
|
||||
**Symptom:** .mobileconfig shows error when installing
|
||||
**Cause:** Invalid XML or missing UUIDs
|
||||
**Solution:** Regenerate with `node generate-mobileconfig.js`
|
||||
|
||||
### Android Shows "Not Trusted"
|
||||
|
||||
**Symptom:** Certificate installs but sites still show warnings
|
||||
**Cause:** Android installs as "user" certificate; some apps don't trust user CAs
|
||||
**Solution:** This is by design. System CA installation requires root access.
|
||||
|
||||
### Landing Page Shows "Loading..."
|
||||
|
||||
**Symptom:** Certificate info stuck on loading state
|
||||
**Cause:** API endpoint not accessible
|
||||
**Solution:** Check that dashcaddy-api server is running and `/api/ca/info` responds
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before deploying to production:
|
||||
|
||||
- [ ] All certificate formats generated successfully
|
||||
- [ ] Landing page loads correctly in browser
|
||||
- [ ] OS detection works (test multiple user agents)
|
||||
- [ ] QR code renders and scans correctly
|
||||
- [ ] Download links work for all file types
|
||||
- [ ] API endpoint returns valid certificate info
|
||||
- [ ] Copy-to-clipboard buttons work
|
||||
- [ ] Platform instruction tabs function correctly
|
||||
- [ ] Responsive design works on mobile viewport
|
||||
- [ ] HTTPS access works after deployment
|
||||
|
||||
## Security Notes
|
||||
|
||||
- **Private Key:** NEVER serve the CA private key (`root.key`). Only public certificates are safe to distribute.
|
||||
- **Fingerprint Verification:** Install scripts verify fingerprint to prevent MITM attacks
|
||||
- **Access Control:** ca.sami should only be accessible on your Tailnet/internal network
|
||||
- **HTTPS Enforcement:** The page itself uses HTTPS (via Caddy's internal CA) to protect the distribution
|
||||
- **No Auto-Execution:** All installation methods require explicit user action
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding features to DashCA:
|
||||
|
||||
1. Test on multiple platforms before committing
|
||||
2. Update this README with new features
|
||||
3. Add relevant sections to troubleshooting guide
|
||||
4. Update CLAUDE.md if deployment process changes
|
||||
5. Ensure backward compatibility with existing certificates
|
||||
|
||||
## Resources
|
||||
|
||||
- **Caddy PKI Documentation:** https://caddyserver.com/docs/caddyfile/directives/tls#pki
|
||||
- **mobileconfig Format:** https://developer.apple.com/documentation/devicemanagement
|
||||
- **OpenSSL Certificate Commands:** https://www.openssl.org/docs/man1.1.1/man1/x509.html
|
||||
- **QR Code Library:** https://github.com/davidshimjs/qrcodejs
|
||||
|
||||
---
|
||||
|
||||
**Part of the DashCaddy project** - Unified management for Docker + Caddy + DNS
|
||||
11
ca/cert-info.json
Normal file
11
ca/cert-info.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Sami Home Network Root CA",
|
||||
"fingerprint": "08:98:A5:63:F5:A1:A2:58:5F:02:D7:A8:A2:54:87:E6:BC:33:96:9F:9B:5D:B0:53:62:20:7F:AF:96:21:29:0E",
|
||||
"validFrom": "Feb 12 07:44:51 2025 GMT",
|
||||
"validUntil": "Dec 22 07:44:51 2034 GMT",
|
||||
"daysUntilExpiration": 3235,
|
||||
"algorithm": "ECDSA P-256 with SHA-256",
|
||||
"issuer": "Sami Home Network Root CA",
|
||||
"serialNumber": "C1DC482220B562C06853903A8956D052",
|
||||
"generatedAt": "2026-02-11T10:43:32.863Z"
|
||||
}
|
||||
1284
ca/index.html
Normal file
1284
ca/index.html
Normal file
File diff suppressed because it is too large
Load Diff
12
ca/intermediate.crt
Normal file
12
ca/intermediate.crt
Normal file
@@ -0,0 +1,12 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBtTCCAVugAwIBAgIRAIyx9ujLhds2Wffi6rROHOYwCgYIKoZIzj0EAwIwJDEi
|
||||
MCAGA1UEAxMZU2FtaSBIb21lIE5ldHdvcmsgUm9vdCBDQTAeFw0yNjAyMTAxMTMx
|
||||
MjBaFw0yNjAyMTcxMTMxMjBaMCwxKjAoBgNVBAMTIVNhbWkgSG9tZSBOZXR3b3Jr
|
||||
IEludGVybWVkaWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL3XMHS8
|
||||
bbGgHsGojPWIgDqHH65nxm/yvfrA/w5rXe1QNZ0oQfXdhUODuu1oTjdQiGSOxp5J
|
||||
N7+r73DIIjDoO1SjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/
|
||||
AgEAMB0GA1UdDgQWBBRvN+rmvteWGd3Gj1ek/5lJWq5MXzAfBgNVHSMEGDAWgBQ1
|
||||
JUJhev790of0c/LsH+PAvsy4iTAKBggqhkjOPQQDAgNIADBFAiEAvWR3KVBGMsWp
|
||||
OEyqcRAmI5kDvfE/zC8bf3IZru5pGFsCIEvil49Fg2ifB8+w5c2T0wjllpsBOUUy
|
||||
HjpIXBIn9ix7
|
||||
-----END CERTIFICATE-----
|
||||
11
ca/root.crt
Normal file
11
ca/root.crt
Normal file
@@ -0,0 +1,11 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBjTCCATKgAwIBAgIRAMHcSCIgtWLAaFOQOolW0FIwCgYIKoZIzj0EAwIwJDEi
|
||||
MCAGA1UEAxMZU2FtaSBIb21lIE5ldHdvcmsgUm9vdCBDQTAeFw0yNTAyMTIwNzQ0
|
||||
NTFaFw0zNDEyMjIwNzQ0NTFaMCQxIjAgBgNVBAMTGVNhbWkgSG9tZSBOZXR3b3Jr
|
||||
IFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATs8K5hvh7qC77kdFgk
|
||||
wyIu6SvzEtrK416lLkQkC+E79xIwGRKsZ7T/gd+0Bk0NMUZBxLww4F2Rl/kt3eGu
|
||||
49rSo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNV
|
||||
HQ4EFgQUNSVCYXr+/dKH9HPy7B/jwL7MuIkwCgYIKoZIzj0EAwIDSQAwRgIhAJE5
|
||||
d02KdZA6V79f4qNfmy3tJMmnL4MA2MHhDQ5qqZyqAiEA2UisGjAXYV3GAGo1d+8C
|
||||
yam9Y42t1K8Fx5q5iy+bs8w=
|
||||
-----END CERTIFICATE-----
|
||||
BIN
ca/root.der
Normal file
BIN
ca/root.der
Normal file
Binary file not shown.
45
ca/root.mobileconfig
Normal file
45
ca/root.mobileconfig
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>root.crt</string>
|
||||
<key>PayloadContent</key>
|
||||
<data>
|
||||
MIIBjTCCATKgAwIBAgIRAMHcSCIgtWLAaFOQOolW0FIwCgYIKoZIzj0EAwIwJDEiMCAGA1UEAxMZU2FtaSBIb21lIE5ldHdvcmsgUm9vdCBDQTAeFw0yNTAyMTIwNzQ0NTFaFw0zNDEyMjIwNzQ0NTFaMCQxIjAgBgNVBAMTGVNhbWkgSG9tZSBOZXR3b3JrIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATs8K5hvh7qC77kdFgkwyIu6SvzEtrK416lLkQkC+E79xIwGRKsZ7T/gd+0Bk0NMUZBxLww4F2Rl/kt3eGu49rSo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUNSVCYXr+/dKH9HPy7B/jwL7MuIkwCgYIKoZIzj0EAwIDSQAwRgIhAJE5d02KdZA6V79f4qNfmy3tJMmnL4MA2MHhDQ5qqZyqAiEA2UisGjAXYV3GAGo1d+8Cyam9Y42t1K8Fx5q5iy+bs8w=
|
||||
</data>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Root CA certificate for Sami Home Network</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Sami Home Network Root CA</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.sami-home.ca.root-ca</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.root</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>059F6B88-E62A-4219-90D5-7FABBE83540A</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Install the Sami Home Network Root CA to trust locally-issued certificates for *.sami domains.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Sami Home Network Root CA</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.sami-home.ca</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Sami Home Network</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>AF495D1C-16AF-44A7-8C6C-173CC8E82FC3</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
50
ca/scripts/generate-all.sh
Normal file
50
ca/scripts/generate-all.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# DashCA Certificate Generation Script
|
||||
# This script generates all required certificate formats
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CA_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
CADDY_CERT_DIR="C:/caddy/certs/pki/authorities/local"
|
||||
|
||||
echo "======================================"
|
||||
echo "DashCA Certificate Format Generator"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
# Step 1: Copy certificates from Caddy
|
||||
echo "[1/4] Copying certificates from Caddy PKI..."
|
||||
if [ ! -f "$CADDY_CERT_DIR/root.crt" ]; then
|
||||
echo "ERROR: Root certificate not found at $CADDY_CERT_DIR/root.crt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "$CADDY_CERT_DIR/root.crt" "$CA_DIR/"
|
||||
cp "$CADDY_CERT_DIR/intermediate.crt" "$CA_DIR/" 2>/dev/null || echo " (Intermediate certificate not found, skipping)"
|
||||
echo " ✓ Certificates copied"
|
||||
|
||||
# Step 2: Generate DER format
|
||||
echo "[2/4] Generating DER format..."
|
||||
openssl x509 -in "$CA_DIR/root.crt" -outform DER -out "$CA_DIR/root.der"
|
||||
echo " ✓ DER format generated: root.der"
|
||||
|
||||
# Step 3: Generate certificate info JSON
|
||||
echo "[3/4] Extracting certificate metadata..."
|
||||
node "$SCRIPT_DIR/generate-cert-info.js"
|
||||
|
||||
# Step 4: Generate Apple mobileconfig
|
||||
echo "[4/4] Generating Apple mobile configuration profile..."
|
||||
node "$SCRIPT_DIR/generate-mobileconfig.js"
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "✓ All certificate formats generated!"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "Files created in: $CA_DIR"
|
||||
ls -lh "$CA_DIR"/*.{crt,der,mobileconfig,json} 2>/dev/null || echo "Files created successfully"
|
||||
echo ""
|
||||
echo "To deploy to production:"
|
||||
echo " cp -r $CA_DIR/* C:/caddy/sites/ca/"
|
||||
echo ""
|
||||
75
ca/scripts/generate-cert-info.js
Normal file
75
ca/scripts/generate-cert-info.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const CERT_PATH = path.join(__dirname, '../root.crt');
|
||||
const OUTPUT_PATH = path.join(__dirname, '../cert-info.json');
|
||||
|
||||
function extractCertInfo() {
|
||||
try {
|
||||
console.log('Extracting certificate information from:', CERT_PATH);
|
||||
|
||||
// Extract SHA-256 fingerprint
|
||||
const fingerprint = execSync(`openssl x509 -in "${CERT_PATH}" -noout -fingerprint -sha256`)
|
||||
.toString()
|
||||
.trim()
|
||||
.split('=')[1];
|
||||
|
||||
// Extract validity dates
|
||||
const dates = execSync(`openssl x509 -in "${CERT_PATH}" -noout -dates`).toString();
|
||||
const notBefore = dates.match(/notBefore=(.*)/)[1].trim();
|
||||
const notAfter = dates.match(/notAfter=(.*)/)[1].trim();
|
||||
|
||||
// Extract subject
|
||||
const subject = execSync(`openssl x509 -in "${CERT_PATH}" -noout -subject`)
|
||||
.toString()
|
||||
.trim()
|
||||
.split('CN = ')[1] || execSync(`openssl x509 -in "${CERT_PATH}" -noout -subject`)
|
||||
.toString()
|
||||
.trim()
|
||||
.split('CN=')[1];
|
||||
|
||||
// Extract serial number
|
||||
const serialNumber = execSync(`openssl x509 -in "${CERT_PATH}" -noout -serial`)
|
||||
.toString()
|
||||
.trim()
|
||||
.split('=')[1];
|
||||
|
||||
// Calculate days until expiration
|
||||
const expirationDate = new Date(notAfter);
|
||||
const today = new Date();
|
||||
const daysUntilExpiration = Math.floor((expirationDate - today) / (1000 * 60 * 60 * 24));
|
||||
|
||||
const certInfo = {
|
||||
name: subject,
|
||||
fingerprint: fingerprint,
|
||||
validFrom: notBefore,
|
||||
validUntil: notAfter,
|
||||
daysUntilExpiration: daysUntilExpiration,
|
||||
algorithm: 'ECDSA P-256 with SHA-256',
|
||||
issuer: subject, // Self-signed root CA
|
||||
serialNumber: serialNumber,
|
||||
generatedAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
fs.writeFileSync(OUTPUT_PATH, JSON.stringify(certInfo, null, 2));
|
||||
console.log('✓ Certificate information extracted successfully!');
|
||||
console.log(' Output:', OUTPUT_PATH);
|
||||
console.log(' Name:', certInfo.name);
|
||||
console.log(' Fingerprint:', certInfo.fingerprint);
|
||||
console.log(' Valid until:', certInfo.validUntil);
|
||||
console.log(' Days until expiration:', certInfo.daysUntilExpiration);
|
||||
|
||||
return certInfo;
|
||||
} catch (error) {
|
||||
console.error('Error extracting certificate information:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
extractCertInfo();
|
||||
}
|
||||
|
||||
module.exports = { extractCertInfo };
|
||||
105
ca/scripts/generate-mobileconfig.js
Normal file
105
ca/scripts/generate-mobileconfig.js
Normal file
@@ -0,0 +1,105 @@
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
const CERT_PATH = path.join(__dirname, '../root.crt');
|
||||
const OUTPUT_PATH = path.join(__dirname, '../root.mobileconfig');
|
||||
|
||||
function generateUUID() {
|
||||
return crypto.randomUUID().toUpperCase();
|
||||
}
|
||||
|
||||
function generateMobileConfig() {
|
||||
try {
|
||||
console.log('Generating Apple mobile configuration profile...');
|
||||
console.log('Reading certificate from:', CERT_PATH);
|
||||
|
||||
// Read certificate
|
||||
const certPem = fs.readFileSync(CERT_PATH, 'utf8');
|
||||
|
||||
// Extract base64 content (remove PEM headers and newlines)
|
||||
const certBase64 = certPem
|
||||
.replace('-----BEGIN CERTIFICATE-----', '')
|
||||
.replace('-----END CERTIFICATE-----', '')
|
||||
.replace(/\s/g, '');
|
||||
|
||||
// Generate UUIDs for profile and payload
|
||||
const profileUUID = generateUUID();
|
||||
const payloadUUID = generateUUID();
|
||||
|
||||
const mobileconfig = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>root.crt</string>
|
||||
<key>PayloadContent</key>
|
||||
<data>
|
||||
${certBase64}
|
||||
</data>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Root CA certificate for Sami Home Network</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Sami Home Network Root CA</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.sami-home.ca.root-ca</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.root</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${payloadUUID}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Install the Sami Home Network Root CA to trust locally-issued certificates for *.sami domains.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Sami Home Network Root CA</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.sami-home.ca</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Sami Home Network</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${profileUUID}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
`;
|
||||
|
||||
fs.writeFileSync(OUTPUT_PATH, mobileconfig);
|
||||
console.log('✓ Mobile configuration profile generated successfully!');
|
||||
console.log(' Output:', OUTPUT_PATH);
|
||||
console.log(' Profile UUID:', profileUUID);
|
||||
console.log(' Payload UUID:', payloadUUID);
|
||||
console.log('\nTo install on iOS:');
|
||||
console.log(' 1. Download root.mobileconfig to your device');
|
||||
console.log(' 2. Open Settings app (it should prompt automatically)');
|
||||
console.log(' 3. Tap "Install Profile" and follow the prompts');
|
||||
console.log(' 4. Go to Settings > General > About > Certificate Trust Settings');
|
||||
console.log(' 5. Enable full trust for "Sami Home Network Root CA"');
|
||||
console.log('\nTo install on macOS:');
|
||||
console.log(' 1. Download root.mobileconfig');
|
||||
console.log(' 2. Open System Settings > Privacy & Security > Profiles');
|
||||
console.log(' 3. Click the profile and click Install');
|
||||
|
||||
return { profileUUID, payloadUUID };
|
||||
} catch (error) {
|
||||
console.error('Error generating mobile configuration profile:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
generateMobileConfig();
|
||||
}
|
||||
|
||||
module.exports = { generateMobileConfig };
|
||||
132
ca/scripts/install.ps1
Normal file
132
ca/scripts/install.ps1
Normal file
@@ -0,0 +1,132 @@
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs the Sami Home Network Root CA certificate to the Trusted Root Certification Authorities store.
|
||||
|
||||
.DESCRIPTION
|
||||
This script downloads the root CA certificate from ca.sami, verifies its fingerprint,
|
||||
and installs it to the local machine's trusted root store. This allows all *.sami domains
|
||||
to be trusted system-wide without browser warnings.
|
||||
|
||||
.NOTES
|
||||
Requires Administrator privileges.
|
||||
For use with DashCA - https://ca.sami
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Configuration
|
||||
$CertUrl = "https://ca.sami/root.crt"
|
||||
$ExpectedFingerprint = "0898A563F5A1A2585F02D7A8A25487E6BC33969F9B5DB053622 07FAF9621290E"
|
||||
$TempFile = "$env:TEMP\sami-root-ca.crt"
|
||||
|
||||
# Colors
|
||||
$Red = [System.ConsoleColor]::Red
|
||||
$Green = [System.ConsoleColor]::Green
|
||||
$Cyan = [System.ConsoleColor]::Cyan
|
||||
$Yellow = [System.ConsoleColor]::Yellow
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor $Cyan
|
||||
Write-Host " DashCA Installer" -ForegroundColor $Cyan
|
||||
Write-Host " Sami Home Network Root CA" -ForegroundColor $Cyan
|
||||
Write-Host "========================================" -ForegroundColor $Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Step 1: Download certificate
|
||||
Write-Host "[1/4] Downloading certificate from $CertUrl..." -ForegroundColor $Cyan
|
||||
try {
|
||||
$ProgressPreference = 'SilentlyContinue' # Disable progress bar for faster download
|
||||
Invoke-WebRequest -Uri $CertUrl -OutFile $TempFile -UseBasicParsing -ErrorAction Stop
|
||||
Write-Host " ✓ Certificate downloaded" -ForegroundColor $Green
|
||||
} catch {
|
||||
Write-Host " ✗ Failed to download certificate" -ForegroundColor $Red
|
||||
Write-Host " Error: $_" -ForegroundColor $Red
|
||||
Write-Host ""
|
||||
Write-Host "Troubleshooting:" -ForegroundColor $Yellow
|
||||
Write-Host " - Ensure you are on the Tailnet/network where ca.sami is accessible" -ForegroundColor $Yellow
|
||||
Write-Host " - Try accessing https://ca.sami in your browser first" -ForegroundColor $Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 2: Verify fingerprint
|
||||
Write-Host "[2/4] Verifying certificate fingerprint..." -ForegroundColor $Cyan
|
||||
try {
|
||||
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($TempFile)
|
||||
$Fingerprint = $Cert.Thumbprint
|
||||
|
||||
$NormalizedExpected = $ExpectedFingerprint -replace '[:\s]', ''
|
||||
$NormalizedActual = $Fingerprint -replace '[:\s]', ''
|
||||
|
||||
if ($NormalizedActual -ne $NormalizedExpected) {
|
||||
Write-Host " ✗ Fingerprint mismatch!" -ForegroundColor $Red
|
||||
Write-Host " Expected: $ExpectedFingerprint" -ForegroundColor $Yellow
|
||||
Write-Host " Got: $Fingerprint" -ForegroundColor $Red
|
||||
Remove-Item $TempFile -Force
|
||||
Write-Host ""
|
||||
Write-Host "SECURITY WARNING: The downloaded certificate does not match the expected fingerprint." -ForegroundColor $Red
|
||||
Write-Host "This could indicate a man-in-the-middle attack or certificate renewal." -ForegroundColor $Red
|
||||
Write-Host "Please verify with your network administrator before proceeding." -ForegroundColor $Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host " ✓ Fingerprint verified: $Fingerprint" -ForegroundColor $Green
|
||||
} catch {
|
||||
Write-Host " ✗ Failed to verify fingerprint" -ForegroundColor $Red
|
||||
Write-Host " Error: $_" -ForegroundColor $Red
|
||||
Remove-Item $TempFile -Force -ErrorAction SilentlyContinue
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 3: Check if already installed
|
||||
Write-Host "[3/4] Checking for existing certificate..." -ForegroundColor $Cyan
|
||||
$ExistingCert = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object { $_.Thumbprint -eq $Fingerprint }
|
||||
if ($ExistingCert) {
|
||||
Write-Host " ℹ Certificate already installed" -ForegroundColor $Yellow
|
||||
Write-Host " Subject: $($ExistingCert.Subject)" -ForegroundColor $Yellow
|
||||
Write-Host " Not After: $($ExistingCert.NotAfter)" -ForegroundColor $Yellow
|
||||
Remove-Item $TempFile -Force
|
||||
Write-Host ""
|
||||
Write-Host "The Sami Home Network Root CA is already trusted on this system." -ForegroundColor $Green
|
||||
Write-Host "No further action needed!" -ForegroundColor $Green
|
||||
Write-Host ""
|
||||
exit 0
|
||||
}
|
||||
Write-Host " ✓ Certificate not yet installed, proceeding..." -ForegroundColor $Green
|
||||
|
||||
# Step 4: Install certificate
|
||||
Write-Host "[4/4] Installing certificate to Trusted Root store..." -ForegroundColor $Cyan
|
||||
try {
|
||||
$ImportedCert = Import-Certificate -FilePath $TempFile -CertStoreLocation Cert:\LocalMachine\Root -ErrorAction Stop
|
||||
Write-Host " ✓ Certificate installed successfully" -ForegroundColor $Green
|
||||
Write-Host " Subject: $($ImportedCert.Subject)" -ForegroundColor $Green
|
||||
Write-Host " Thumbprint: $($ImportedCert.Thumbprint)" -ForegroundColor $Green
|
||||
} catch {
|
||||
Write-Host " ✗ Failed to install certificate" -ForegroundColor $Red
|
||||
Write-Host " Error: $_" -ForegroundColor $Red
|
||||
Remove-Item $TempFile -Force -ErrorAction SilentlyContinue
|
||||
Write-Host ""
|
||||
Write-Host "Installation failed. Please ensure you are running as Administrator." -ForegroundColor $Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Cleanup
|
||||
Remove-Item $TempFile -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor $Green
|
||||
Write-Host " SUCCESS!" -ForegroundColor $Green
|
||||
Write-Host "========================================" -ForegroundColor $Green
|
||||
Write-Host ""
|
||||
Write-Host "The Sami Home Network Root CA has been installed to your Trusted Root store." -ForegroundColor $Green
|
||||
Write-Host ""
|
||||
Write-Host "What's next:" -ForegroundColor $Cyan
|
||||
Write-Host " ✓ All *.sami domains will now be trusted system-wide" -ForegroundColor $Green
|
||||
Write-Host " ✓ Browsers (Edge, Chrome, Firefox) will no longer show security warnings" -ForegroundColor $Green
|
||||
Write-Host " ✓ Applications will trust HTTPS connections to your local services" -ForegroundColor $Green
|
||||
Write-Host ""
|
||||
Write-Host "Test it out:" -ForegroundColor $Cyan
|
||||
Write-Host " Visit https://status.sami or any other *.sami service" -ForegroundColor $Yellow
|
||||
Write-Host " The connection should show as secure with no warnings" -ForegroundColor $Yellow
|
||||
Write-Host ""
|
||||
220
ca/scripts/install.sh
Normal file
220
ca/scripts/install.sh
Normal file
@@ -0,0 +1,220 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# DashCA Installer - Sami Home Network Root CA
|
||||
# Installs the root CA certificate system-wide on Linux and macOS
|
||||
#
|
||||
# Usage: curl -fsSL https://ca.sami/install.sh | sudo bash
|
||||
#
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
CERT_URL="https://ca.sami/root.crt"
|
||||
EXPECTED_FP="08:98:A5:63:F5:A1:A2:58:5F:02:D7:A8:A2:54:87:E6:BC:33:96:9F:9B:5D:B0:53:62:20:7F:AF:96:21:29:0E"
|
||||
CERT_NAME="Sami_Home_Network_Root_CA"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
CYAN='\033[0;36m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}========================================${NC}"
|
||||
echo -e "${CYAN} DashCA Installer${NC}"
|
||||
echo -e "${CYAN} Sami Home Network Root CA${NC}"
|
||||
echo -e "${CYAN}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
# Check for root/sudo
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "${RED}✗ This script requires root privileges${NC}"
|
||||
echo ""
|
||||
echo "Please run with sudo:"
|
||||
echo -e " ${YELLOW}curl -fsSL https://ca.sami/install.sh | sudo bash${NC}"
|
||||
echo ""
|
||||
echo "Or download first, then run:"
|
||||
echo -e " ${YELLOW}curl -o install.sh https://ca.sami/install.sh${NC}"
|
||||
echo -e " ${YELLOW}sudo bash install.sh${NC}"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect OS
|
||||
echo -e "${CYAN}[1/6] Detecting operating system...${NC}"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
OS="macos"
|
||||
OS_NAME="macOS"
|
||||
elif [[ -f /etc/os-release ]]; then
|
||||
. /etc/os-release
|
||||
if [[ "$ID" == "debian" ]] || [[ "$ID" == "ubuntu" ]] || [[ "$ID_LIKE" == *"debian"* ]]; then
|
||||
OS="debian"
|
||||
OS_NAME="Debian/Ubuntu"
|
||||
elif [[ "$ID" == "fedora" ]] || [[ "$ID" == "rhel" ]] || [[ "$ID" == "centos" ]] || [[ "$ID_LIKE" == *"fedora"* ]] || [[ "$ID_LIKE" == *"rhel"* ]]; then
|
||||
OS="redhat"
|
||||
OS_NAME="RedHat/CentOS/Fedora"
|
||||
elif [[ "$ID" == "arch" ]] || [[ "$ID_LIKE" == *"arch"* ]]; then
|
||||
OS="arch"
|
||||
OS_NAME="Arch Linux"
|
||||
else
|
||||
OS="unknown"
|
||||
OS_NAME="Unknown Linux"
|
||||
fi
|
||||
elif [[ -f /etc/redhat-release ]]; then
|
||||
OS="redhat"
|
||||
OS_NAME="RedHat/CentOS"
|
||||
elif [[ -f /etc/arch-release ]]; then
|
||||
OS="arch"
|
||||
OS_NAME="Arch Linux"
|
||||
else
|
||||
OS="unknown"
|
||||
OS_NAME="Unknown"
|
||||
fi
|
||||
|
||||
if [[ "$OS" == "unknown" ]]; then
|
||||
echo -e "${RED} ✗ Unsupported operating system${NC}"
|
||||
echo ""
|
||||
echo "This script supports:"
|
||||
echo " - Debian/Ubuntu"
|
||||
echo " - RedHat/CentOS/Fedora"
|
||||
echo " - Arch Linux"
|
||||
echo " - macOS"
|
||||
echo ""
|
||||
echo "For manual installation, download the certificate:"
|
||||
echo -e " ${YELLOW}curl -O $CERT_URL${NC}"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} ✓ Detected: $OS_NAME${NC}"
|
||||
|
||||
# Download certificate
|
||||
echo -e "${CYAN}[2/6] Downloading certificate from $CERT_URL...${NC}"
|
||||
TEMP_CERT=$(mktemp)
|
||||
if ! curl -fsSL "$CERT_URL" -o "$TEMP_CERT"; then
|
||||
echo -e "${RED} ✗ Failed to download certificate${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Troubleshooting:${NC}"
|
||||
echo " - Ensure you are on the Tailnet/network where ca.sami is accessible"
|
||||
echo " - Try accessing https://ca.sami in your browser first"
|
||||
echo " - Check your network connection"
|
||||
rm -f "$TEMP_CERT"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN} ✓ Certificate downloaded${NC}"
|
||||
|
||||
# Verify fingerprint
|
||||
echo -e "${CYAN}[3/6] Verifying certificate fingerprint...${NC}"
|
||||
if ! command -v openssl &> /dev/null; then
|
||||
echo -e "${RED} ✗ OpenSSL not found${NC}"
|
||||
echo "Please install OpenSSL to verify certificate fingerprint"
|
||||
rm -f "$TEMP_CERT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ACTUAL_FP=$(openssl x509 -in "$TEMP_CERT" -noout -fingerprint -sha256 | cut -d= -f2)
|
||||
|
||||
if [[ "$ACTUAL_FP" != "$EXPECTED_FP" ]]; then
|
||||
echo -e "${RED} ✗ Fingerprint mismatch!${NC}"
|
||||
echo -e "${YELLOW} Expected: $EXPECTED_FP${NC}"
|
||||
echo -e "${RED} Got: $ACTUAL_FP${NC}"
|
||||
rm -f "$TEMP_CERT"
|
||||
echo ""
|
||||
echo -e "${RED}SECURITY WARNING: The downloaded certificate does not match the expected fingerprint.${NC}"
|
||||
echo -e "${RED}This could indicate a man-in-the-middle attack or certificate renewal.${NC}"
|
||||
echo -e "${RED}Please verify with your network administrator before proceeding.${NC}"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} ✓ Fingerprint verified${NC}"
|
||||
|
||||
# Extract certificate details
|
||||
echo -e "${CYAN}[4/6] Extracting certificate information...${NC}"
|
||||
CERT_SUBJECT=$(openssl x509 -in "$TEMP_CERT" -noout -subject | sed 's/subject=//')
|
||||
CERT_NOT_AFTER=$(openssl x509 -in "$TEMP_CERT" -noout -enddate | sed 's/notAfter=//')
|
||||
echo -e "${GREEN} ✓ Subject: $CERT_SUBJECT${NC}"
|
||||
echo -e "${GREEN} ✓ Valid until: $CERT_NOT_AFTER${NC}"
|
||||
|
||||
# Check if already installed
|
||||
echo -e "${CYAN}[5/6] Checking for existing installation...${NC}"
|
||||
ALREADY_INSTALLED=false
|
||||
|
||||
case "$OS" in
|
||||
debian)
|
||||
if [[ -f "/usr/local/share/ca-certificates/${CERT_NAME}.crt" ]]; then
|
||||
ALREADY_INSTALLED=true
|
||||
fi
|
||||
;;
|
||||
redhat)
|
||||
if [[ -f "/etc/pki/ca-trust/source/anchors/${CERT_NAME}.crt" ]]; then
|
||||
ALREADY_INSTALLED=true
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
if [[ -f "/etc/ca-certificates/trust-source/anchors/${CERT_NAME}.crt" ]]; then
|
||||
ALREADY_INSTALLED=true
|
||||
fi
|
||||
;;
|
||||
macos)
|
||||
if security find-certificate -a -c "$CERT_SUBJECT" /Library/Keychains/System.keychain &>/dev/null; then
|
||||
ALREADY_INSTALLED=true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$ALREADY_INSTALLED" == "true" ]]; then
|
||||
echo -e "${YELLOW} ℹ Certificate already installed${NC}"
|
||||
rm -f "$TEMP_CERT"
|
||||
echo ""
|
||||
echo -e "${GREEN}The Sami Home Network Root CA is already trusted on this system.${NC}"
|
||||
echo -e "${GREEN}No further action needed!${NC}"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} ✓ Certificate not yet installed, proceeding...${NC}"
|
||||
|
||||
# Install based on OS
|
||||
echo -e "${CYAN}[6/6] Installing certificate...${NC}"
|
||||
case "$OS" in
|
||||
debian)
|
||||
cp "$TEMP_CERT" "/usr/local/share/ca-certificates/${CERT_NAME}.crt"
|
||||
update-ca-certificates
|
||||
echo -e "${GREEN} ✓ Certificate installed via update-ca-certificates${NC}"
|
||||
;;
|
||||
redhat)
|
||||
cp "$TEMP_CERT" "/etc/pki/ca-trust/source/anchors/${CERT_NAME}.crt"
|
||||
update-ca-trust
|
||||
echo -e "${GREEN} ✓ Certificate installed via update-ca-trust${NC}"
|
||||
;;
|
||||
arch)
|
||||
cp "$TEMP_CERT" "/etc/ca-certificates/trust-source/anchors/${CERT_NAME}.crt"
|
||||
trust extract-compat
|
||||
echo -e "${GREEN} ✓ Certificate installed via trust extract-compat${NC}"
|
||||
;;
|
||||
macos)
|
||||
security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$TEMP_CERT"
|
||||
echo -e "${GREEN} ✓ Certificate installed to System Keychain${NC}"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Cleanup
|
||||
rm -f "$TEMP_CERT"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} SUCCESS!${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}The Sami Home Network Root CA has been installed system-wide.${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}What's next:${NC}"
|
||||
echo -e " ${GREEN}✓${NC} All *.sami domains will now be trusted"
|
||||
echo -e " ${GREEN}✓${NC} Browsers will no longer show security warnings"
|
||||
echo -e " ${GREEN}✓${NC} Applications will trust HTTPS connections to your local services"
|
||||
echo ""
|
||||
echo -e "${CYAN}Test it out:${NC}"
|
||||
echo -e " ${YELLOW}Visit https://status.sami or any other *.sami service${NC}"
|
||||
echo -e " ${YELLOW}The connection should show as secure with no warnings${NC}"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user