From 82796c3801c1c8fabdbfd75c82bdde66dbe39ec3 Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 23 Feb 2024 17:44:10 +0100 Subject: [PATCH] Anonymize error message (datarhei/restreamer#688) --- src/utils/anonymizer.js | 51 +++++++++++++++++++++++++++++++++++ src/utils/restreamer.js | 59 +++++++++++++++++++++-------------------- src/views/Main/index.js | 3 ++- 3 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 src/utils/anonymizer.js diff --git a/src/utils/anonymizer.js b/src/utils/anonymizer.js new file mode 100644 index 0000000..b022699 --- /dev/null +++ b/src/utils/anonymizer.js @@ -0,0 +1,51 @@ +import urlparser from 'url-parse'; + +const anonymize_url = (url) => { + let u = urlparser(url, true); + + if (u.hostname !== 'localhost') { + return `${u.protocol}//[anonymized]`; + } + + if (u.auth.length !== 0) { + u.username = '***'; + u.password = '***'; + } + + if (u.protocol === 'rtmp:') { + if ('token' in u.query) { + u.query.token = '***'; + } + } else if (u.protocol === 'srt') { + if ('streamid' in u.query) { + u.query.streamid = '***'; + } + + if ('passphrase' in u.query) { + u.query.passphrase = '***'; + } + } + + return u.toString(); +}; + +const anonymize = (text) => { + const regex = /(?:([a-z0-9\\]+):)?\/[A-Za-z0-9-._~!$&'()*+,;=:@?/{}%\\]*/gm; + + return text.replaceAll(regex, (match, scheme) => { + console.log('text', text, 'match', match, 'scheme', scheme); + if (scheme) { + match = match.replace(scheme, scheme.replaceAll('\\', '')); + return anonymize_url(match); + } + + const pathElm = match.split('/').filter((p) => p.length !== 0); + if (pathElm.length < 2) { + return match; + } + + return `/[anonymized]/${pathElm.pop()}`; + }); +}; + +export { anonymize, anonymize_url }; diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js index cfc52ba..d64d81c 100644 --- a/src/utils/restreamer.js +++ b/src/utils/restreamer.js @@ -11,6 +11,7 @@ import * as M from './metadata'; import * as Storage from './storage'; import * as Version from '../version'; import API from './api'; +import { anonymize } from './anonymizer'; class Restreamer { constructor(address) { @@ -3030,51 +3031,35 @@ class Restreamer { return null; } - const regex = /(?:([a-z]+):)?\/[^\s]*/gm; - const replace = (s) => { - return s.replaceAll(regex, (match, scheme) => { - if (scheme) { - return `${scheme}://[anonymized]`; - } - - const pathElm = match.split('/').filter((p) => p.length !== 0); - if (pathElm.length < 2) { - return match; - } - - return `/[anonymized]/${pathElm.pop()}`; - }); - }; - if (p.config) { - p.config.options = p.config.options.map(replace); + p.config.options = p.config.options.map(anonymize); for (let i in p.config.input) { - p.config.input[i].address = replace(p.config.input[i].address); - p.config.input[i].options = p.config.input[i].options.map(replace); + p.config.input[i].address = anonymize(p.config.input[i].address); + p.config.input[i].options = p.config.input[i].options.map(anonymize); } for (let i in p.config.output) { - p.config.output[i].address = replace(p.config.output[i].address); - p.config.output[i].options = p.config.output[i].options.map(replace); + p.config.output[i].address = anonymize(p.config.output[i].address); + p.config.output[i].options = p.config.output[i].options.map(anonymize); } } if (p.state) { for (let i in p.state.progress.inputs) { - p.state.progress.inputs[i].address = replace(p.state.progress.inputs[i].address); + p.state.progress.inputs[i].address = anonymize(p.state.progress.inputs[i].address); } for (let i in p.state.progress.outputs) { - p.state.progress.outputs[i].address = replace(p.state.progress.outputs[i].address); + p.state.progress.outputs[i].address = anonymize(p.state.progress.outputs[i].address); } if (!p.state.command) { p.state.command = []; } - p.state.command = p.state.command.map(replace); - p.state.last_logline = replace(p.state.last_logline); + p.state.command = p.state.command.map(anonymize); + p.state.last_logline = anonymize(p.state.last_logline); } if (p.report) { @@ -3082,12 +3067,12 @@ class Restreamer { p.report.prelude = []; } - p.report.prelude = p.report.prelude.map(replace); - p.report.log = p.report.log.map((l) => [l[0], replace(l[1])]); + p.report.prelude = p.report.prelude.map(anonymize); + p.report.log = p.report.log.map((l) => [l[0], anonymize(l[1])]); for (let i in p.report.history) { - p.report.history[i].prelude = p.report.history[i].prelude.map(replace); - p.report.history[i].log = p.report.history[i].log.map((l) => [l[0], replace(l[1])]); + p.report.history[i].prelude = p.report.history[i].prelude.map(anonymize); + p.report.history[i].log = p.report.history[i].log.map((l) => [l[0], anonymize(l[1])]); } } @@ -3348,6 +3333,20 @@ class Restreamer { config.storage.memory.auth.username = '[anonymized]'; config.storage.memory.auth.password = '[anonymized]'; + config.storage.s3 = config.storage.s3.map((e) => { + return { + ...e, + auth: { + ...e.auth, + username: '[anonymized]', + password: '[anonymized]', + }, + endpoint: '[anonymized]', + access_key_id: '[anonymized]', + secret_access_key: '[anonymized]', + }; + }); + if (config.storage.cors.origins.length !== 1 || config.storage.cors.origins[0] !== '*') { config.storage.cors.origins = config.storage.cors.origins.map((e) => '[anonymized]'); } @@ -3355,6 +3354,8 @@ class Restreamer { config.rtmp.app = '[anonymized]'; config.rtmp.token = '[anonymized]'; + config.ffmpeg.binary = anonymize(config.ffmpeg.binary); + config.service.token = '[anonymized]'; config.sessions.ip_ignorelist = config.sessions.ip_ignorelist.map((e) => '[anonymized]'); diff --git a/src/views/Main/index.js b/src/views/Main/index.js index ed269b2..49c851b 100644 --- a/src/views/Main/index.js +++ b/src/views/Main/index.js @@ -11,6 +11,7 @@ import Typography from '@mui/material/Typography'; import WarningIcon from '@mui/icons-material/Warning'; import * as M from '../../utils/metadata'; +import { anonymize } from '../../utils/anonymizer'; import useInterval from '../../hooks/useInterval'; import ActionButton from '../../misc/ActionButton'; import CopyButton from '../../misc/CopyButton'; @@ -350,7 +351,7 @@ export default function Main(props) { - Error: {$state.progress.error || 'unknown'} + Error: {anonymize($state.progress.error) || 'unknown'}