diff --git a/public/js/admin.js b/public/js/admin.js index bf5b541..986af67 100644 --- a/public/js/admin.js +++ b/public/js/admin.js @@ -1354,7 +1354,8 @@ function renderTls(tls) { itself before it lapses, and devices that trust the authority keep working without being touched again.
`; diff --git a/push-to-gitea.ps1 b/push-to-gitea.ps1 index d11b74f..c11d9a7 100644 --- a/push-to-gitea.ps1 +++ b/push-to-gitea.ps1 @@ -41,6 +41,30 @@ if ((git remote) -match '^origin$') { git remote add origin $Remote } +# ------------------------------------------------- finish what was started + +# A rebase or merge left half-done blocks everything that follows, and the error +# git gives is easy to mistake for a push problem. Catch it here and say plainly +# what to do. +$gitDir = (git rev-parse --git-dir 2>$null) +if ($gitDir) { + $stuck = @('rebase-merge', 'rebase-apply', 'MERGE_HEAD', 'CHERRY_PICK_HEAD') | + Where-Object { Test-Path (Join-Path $gitDir $_) } + if ($stuck) { + Write-Host '' + Write-Host 'There is an unfinished rebase or merge in this folder.' -ForegroundColor Red + Write-Host 'Nothing else can happen until it is settled. Your options:' -ForegroundColor Yellow + Write-Host '' + Write-Host ' git rebase --abort throw the attempt away and go back to how things were' + Write-Host ' git status see which files still need attention' + Write-Host ' git rebase --continue after fixing the files git listed' + Write-Host '' + Write-Host 'If you are unsure, "git rebase --abort" is the safe one. It puts the' -ForegroundColor Yellow + Write-Host 'folder back exactly as it was before the rebase started.' -ForegroundColor Yellow + exit 1 + } +} + # ---------------------------------------------------------------- commit git add -A diff --git a/push-to-gitea.sh b/push-to-gitea.sh index 5aa3ed1..2ef8e64 100644 --- a/push-to-gitea.sh +++ b/push-to-gitea.sh @@ -19,6 +19,26 @@ else git remote add origin "$REMOTE" fi +# An unfinished rebase or merge blocks everything below, and git's own error is +# easy to mistake for a push problem. +GIT_DIR_PATH=$(git rev-parse --git-dir 2>/dev/null || echo .git) +for marker in rebase-merge rebase-apply MERGE_HEAD CHERRY_PICK_HEAD; do + if [ -e "$GIT_DIR_PATH/$marker" ]; then + cat >&2 <<'MSG' + +There is an unfinished rebase or merge in this folder. +Nothing else can happen until it is settled: + + git rebase --abort throw the attempt away, back to how things were + git status see which files still need attention + git rebase --continue after fixing the files git listed + +If unsure, "git rebase --abort" is the safe one. +MSG + exit 1 + fi +done + git add -A if [ -n "$(git status --porcelain)" ]; then read -r -p "Describe this change (enter for a dated default): " MSG diff --git a/src/routes/admin.js b/src/routes/admin.js index e6d9fca..cfdfe53 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -1224,6 +1224,24 @@ router.get('/tls/ca.crt', (req, res) => { res.send(ca); }); +/** + * The same authority in DER form, for Jamf Pro and anything else built on Apple's + * tooling. Offered as .cer and .der because different consoles insist on + * different extensions for the identical bytes. + */ +router.get(['/tls/ca.cer', '/tls/ca.der'], (req, res) => { + try { + const der = tls.caCertificateDer(); + if (!der) return res.status(404).send('No certificate authority has been generated yet.'); + const ext = req.path.endsWith('.der') ? 'der' : 'cer'; + res.setHeader('Content-Type', 'application/pkix-cert'); + res.setHeader('Content-Disposition', `attachment; filename="visitor-signin-ca.${ext}"`); + res.send(der); + } catch (err) { + res.status(500).send(`Could not convert the certificate: ${err.message}`); + } +}); + router.post('/tls/renew', requireOwner, (req, res) => { try { // A brand new CA means every kiosk device has to trust it again, so it is diff --git a/src/server.js b/src/server.js index ffb5740..3ea6366 100644 --- a/src/server.js +++ b/src/server.js @@ -121,6 +121,25 @@ function startRedirectServer() { http .createServer((req, res) => { + // DER for Apple tooling, PEM for everything else. + if (req.url === '/ca.cer' || req.url === '/ca.der') { + try { + const der = tls.caCertificateDer(); + if (!der) { + res.writeHead(404, { 'Content-Type': 'text/plain' }); + return res.end('No certificate authority has been generated yet.'); + } + res.writeHead(200, { + 'Content-Type': 'application/pkix-cert', + 'Content-Disposition': 'attachment; filename="visitor-signin-ca.cer"', + }); + return res.end(der); + } catch (err) { + res.writeHead(500, { 'Content-Type': 'text/plain' }); + return res.end(`Could not convert the certificate: ${err.message}`); + } + } + if (req.url === '/ca.crt' || req.url === '/ca.pem') { const ca = tls.caCertificate(); if (!ca) { diff --git a/src/tls.js b/src/tls.js index 4d93e4c..1145c1d 100644 --- a/src/tls.js +++ b/src/tls.js @@ -225,6 +225,19 @@ export function describe() { }; } +/** + * The CA in DER form. + * + * The .crt on disk is PEM: base64 text between BEGIN/END lines. Apple's tooling, + * and therefore Jamf Pro's certificate payload, wants the raw binary DER instead + * and rejects the file on its extension. Same certificate, different wrapper. + */ +export function caCertificateDer() { + const p = paths(); + if (!fs.existsSync(p.caCert)) return null; + return openssl(['x509', '-in', p.caCert, '-outform', 'der']); +} + export function caCertificate() { const p = paths(); return fs.existsSync(p.caCert) ? fs.readFileSync(p.caCert) : null;