Fix self-signed certificates on ubuntu + v8.0.2:

* On some Ubuntu server, the self-signed certificates generation fails:
  * See [issue #268](https://github.com/JohnXLivingston/peertube-plugin-livechat/issues/268)
  * This prevents the bot to connect to the server
  * As a fallback, we directly call openssl to generate the certificates
This commit is contained in:
John Livingston 2023-09-27 14:29:17 +02:00
parent 05b45fe6b5
commit 5614987901
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
5 changed files with 96 additions and 17 deletions

View File

@ -1,5 +1,14 @@
# Changelog
## 8.0.2
### Minor changes and fixes
* On some Ubuntu server, the self-signed certificates generation fails:
* See [issue #268](https://github.com/JohnXLivingston/peertube-plugin-livechat/issues/268)
* This prevents the bot to connect to the server
* As a fallback, we directly call openssl to generate the certificates
## 8.0.1
### Minor changes and fixes

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "peertube-plugin-livechat",
"version": "8.0.1",
"version": "8.0.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "peertube-plugin-livechat",
"version": "8.0.1",
"version": "8.0.2",
"license": "AGPL-3.0",
"dependencies": {
"async": "^3.2.2",

View File

@ -1,7 +1,7 @@
{
"name": "peertube-plugin-livechat",
"description": "PeerTube plugin livechat: create chat rooms for your Peertube lives!",
"version": "8.0.1",
"version": "8.0.2",
"license": "AGPL-3.0",
"author": {
"name": "John Livingston",

View File

@ -11,6 +11,7 @@ interface ProsodyDebuggerOptions {
interface DebugContent {
renewCertCheckInterval?: number
renewSelfSignedCertInterval?: number
useOpenSSL?: boolean
logRotateCheckInterval?: number
logRotateEvery?: number
remoteServerInfosMaxAge?: number
@ -25,7 +26,7 @@ type DebugNumericValue = 'renewCertCheckInterval'
| 'logRotateCheckInterval'
| 'remoteServerInfosMaxAge'
type DebugBooleanValue = 'alwaysPublishXMPPRoom' | 'enablePodcastChatTagForNonLive'
type DebugBooleanValue = 'alwaysPublishXMPPRoom' | 'enablePodcastChatTagForNonLive' | 'useOpenSSL'
let debugContent: DebugContent | null | false = null
function _readDebugFile (options: RegisterServerOptions): DebugContent | false {
@ -58,6 +59,7 @@ function _readDebugFile (options: RegisterServerOptions): DebugContent | false {
debugContent.logRotateEvery = _getNumericOptions(options, json, 'log_rotate_every')
debugContent.renewCertCheckInterval = _getNumericOptions(options, json, 'renew_cert_check_interval')
debugContent.renewSelfSignedCertInterval = _getNumericOptions(options, json, 'renew_self_signed_cert_interval')
debugContent.useOpenSSL = json.use_openssl === true
debugContent.remoteServerInfosMaxAge = _getNumericOptions(options, json, 'remote_server_infos_max_age')
debugContent.alwaysPublishXMPPRoom = json.always_publish_xmpp_room === true
debugContent.enablePodcastChatTagForNonLive = json.enable_podcast_chat_tag_for_nonlive === true

View File

@ -1,9 +1,10 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import type { ProsodyConfig } from './config'
import { debugNumericParameter } from '../debug'
import { debugNumericParameter, isDebugMode } from '../debug'
import { prosodyCtl, reloadProsody } from './ctl'
import * as path from 'path'
import * as fs from 'fs'
import * as child_process from 'child_process'
interface Renew {
timer: NodeJS.Timer
@ -61,18 +62,28 @@ async function ensureProsodyCertificates (options: RegisterServerOptions, config
}
// Using: prososyctl --config /.../prosody.cfg.lua cert generate prosodyDomain.tld
await prosodyCtl(options, 'cert', {
additionalArgs: ['generate', prosodyDomain],
yesMode: true,
stdErrFilter: (data) => {
// For an unknow reason, `prosodyctl cert generate` outputs openssl data on stderr...
// So we filter these logs.
if (data.match(/Generating \w+ private key/)) { return false }
if (data.match(/^[.+o*\n]*$/m)) { return false }
if (data.match(/e is \d+/)) { return false }
return true
}
})
if (!isDebugMode(options, 'useOpenSSL')) {
await prosodyCtl(options, 'cert', {
additionalArgs: ['generate', prosodyDomain],
yesMode: true,
stdErrFilter: (data) => {
// For an unknow reason, `prosodyctl cert generate` outputs openssl data on stderr...
// So we filter these logs.
if (data.match(/Generating \w+ private key/)) { return false }
if (data.match(/^[.+o*\n]*$/m)) { return false }
if (data.match(/e is \d+/)) { return false }
return true
}
})
}
// Note: it seems that on Ubuntu, "prosocyctl cert generate" won't work.
// See https://github.com/JohnXLivingston/peertube-plugin-livechat/issues/268
// So, if the file still does not exist, we will fallback to openssl:
if (!fs.existsSync(filepath)) {
logger.warn(`The certificate ${filepath} creation (using prosodyctl) failed, trying to use openssl`)
await _generateSelfSignedUsingOpenSSL(options, path.dirname(filepath), prosodyDomain)
}
}
async function renewCheck (options: RegisterServerOptions, config: ProsodyConfig): Promise<void> {
@ -159,6 +170,63 @@ function _filePathToTest (options: RegisterServerOptions, config: ProsodyConfig)
return path.resolve(config.paths.certs, config.host + '.crt')
}
async function _generateSelfSignedUsingOpenSSL (
options: RegisterServerOptions,
dir: string,
prosodyDomain: string
): Promise<void> {
const logger = options.peertubeHelpers.logger
logger.info('Calling openssl to generate a self-signed certificate.')
return new Promise((resolve, reject) => {
// Here we want to launch something like:
// eslint-disable-next-line max-len
// openssl req -new -x509 -newkey rsa:2048 -nodes -keyout prosodyDomain.key -days 365 -sha256 -out prosodyDomain.crt -utf8 -subj /CN=prosodyDomain
const cmdArgs = [
'req',
'-new',
'-x509',
'-newkey',
'rsa:2048',
'-nodes',
'-keyout',
path.resolve(dir, `${prosodyDomain}.key`),
'-days',
'365',
'-sha256',
'-out',
path.resolve(dir, `${prosodyDomain}.crt`),
'-utf8',
'-subj',
`/CN=${prosodyDomain}`
]
const spawned = child_process.spawn('openssl', cmdArgs, {
cwd: dir,
env: {
...process.env
}
})
// spawned.stdout.on('data', (data) => {
// logger.debug(`OpenSSL output: ${data as string}`)
// })
// spawned.stderr.on('data', (data) => {
// // Note: openssl writes on stderr... not loging anything.
// // logger.error(`Spawned openssl command has errors: ${data as string}`)
// })
spawned.on('error', (err) => {
logger.error(`Spawned openssl command failed: ${err as unknown as string}`)
reject(err)
})
// on 'close' and not 'exit', to be sure everything is done
// (else it can cause trouble by cleaning AppImage extract too soon)
spawned.on('close', () => {
resolve()
})
})
}
export {
ensureProsodyCertificates,
startProsodyCertificatesRenewCheck,