New option to use and configure Prosody mod_firewall WIP (#97):

* new setting
* new configuration screen for Peertube admins
* include the mod_firewall module
* load mod_firewall if enabled
* sys admin can disable the firewall config editing by creating a
  special file on the disk
* user documentation
This commit is contained in:
John Livingston
2024-08-12 18:17:31 +02:00
parent 481f265a44
commit 8e99199f29
76 changed files with 7577 additions and 300 deletions

View File

@ -14,6 +14,7 @@ import { initFederationServerInfosApiRouter } from './api/federation-server-info
import { initConfigurationApiRouter } from './api/configuration'
import { initPromoteApiRouter } from './api/promote'
import { initEmojisRouter } from './emojis'
import { initAdminFirewallApiRouter } from './api/admin/firewall'
/**
* Initiate API routes
@ -45,6 +46,8 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
await initPromoteApiRouter(options, router)
await initEmojisRouter(options, router)
await initAdminFirewallApiRouter(options, router)
if (isDebugMode(options)) {
// Only add this route if the debug mode is enabled at time of the server launch.
// Note: the isDebugMode will be tested again when the API is called.

View File

@ -0,0 +1,81 @@
// SPDX-FileCopyrightText: 2024 John Livingston <https://www.john-livingston.fr/>
//
// SPDX-License-Identifier: AGPL-3.0-only
import type { RegisterServerOptions } from '@peertube/peertube-types'
import type { Router, Request, Response, NextFunction } from 'express'
import type { AdminFirewallConfiguration } from '../../../../../shared/lib/types'
import { asyncMiddleware, RequestPromiseHandler } from '../../../middlewares/async'
import { checkUserIsAdminMiddleware } from '../../../middlewares/is-admin'
import {
getModFirewallConfig, sanitizeModFirewallConfig, saveModFirewallConfig, canEditFirewallConfig
} from '../../../firewall/config'
import { getProsodyFilePaths, writeProsodyConfig } from '../../../prosody/config'
import { reloadProsody } from '../../../prosody/ctl'
function canEditFirewallConfigMiddleware (options: RegisterServerOptions): RequestPromiseHandler {
return async (req: Request, res: Response, next: NextFunction) => {
if (!await canEditFirewallConfig(options)) {
options.peertubeHelpers.logger.info('Firewall configuration editing is disabled')
res.sendStatus(403)
return
}
next()
}
}
async function initAdminFirewallApiRouter (options: RegisterServerOptions, router: Router): Promise<void> {
const logger = options.peertubeHelpers.logger
router.get('/admin/firewall', asyncMiddleware([
checkUserIsAdminMiddleware(options),
canEditFirewallConfigMiddleware(options),
async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
try {
const prosodyPaths = await getProsodyFilePaths(options)
const result: AdminFirewallConfiguration = await getModFirewallConfig(options, prosodyPaths.modFirewallFiles)
res.status(200)
res.json(result)
} catch (err) {
options.peertubeHelpers.logger.error(err)
res.sendStatus(500)
}
}
]))
router.post('/admin/firewall', asyncMiddleware([
checkUserIsAdminMiddleware(options),
canEditFirewallConfigMiddleware(options),
async (req: Request, res: Response, _next: NextFunction): Promise<void> => {
try {
const prosodyPaths = await getProsodyFilePaths(options)
let data: AdminFirewallConfiguration
try {
data = await sanitizeModFirewallConfig(options, req.body)
} catch (err) {
logger.error(err)
res.sendStatus(400)
return
}
await saveModFirewallConfig(options, prosodyPaths.modFirewallFiles, data)
logger.info('Just saved a new mod_firewall const, must rewrite Prosody configuration file, and reload Prosody.')
await writeProsodyConfig(options)
await reloadProsody(options)
const result: AdminFirewallConfiguration = await getModFirewallConfig(options, prosodyPaths.modFirewallFiles)
res.status(200)
res.json(result)
} catch (err) {
options.peertubeHelpers.logger.error(err)
res.sendStatus(500)
}
}
]))
}
export {
initAdminFirewallApiRouter
}