Remove login details before logging stream source (#45398)

* Remove login details before logging stream source

* Convert to str before re

* Use compiled RE

* Add tests and filter log message in worker

* Update import

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* isort

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
uvjustin 2021-03-23 14:30:45 +08:00 committed by GitHub
parent 55b689b464
commit cd455e296e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 3 deletions

View File

@ -15,6 +15,7 @@ tokens are expired. Alternatively, a Stream can be configured with keepalive
to always keep workers active.
"""
import logging
import re
import secrets
import threading
import time
@ -38,6 +39,8 @@ from .hls import async_setup_hls
_LOGGER = logging.getLogger(__name__)
STREAM_SOURCE_RE = re.compile("//(.*):(.*)@")
def create_stream(hass, stream_source, options=None):
"""Create a stream with the specified identfier based on the source url.
@ -173,7 +176,9 @@ class Stream:
target=self._run_worker,
)
self._thread.start()
_LOGGER.info("Started stream: %s", self.source)
_LOGGER.info(
"Started stream: %s", STREAM_SOURCE_RE.sub("//", str(self.source))
)
def update_source(self, new_source):
"""Restart the stream with a new stream source."""
@ -239,7 +244,9 @@ class Stream:
self._thread_quit.set()
self._thread.join()
self._thread = None
_LOGGER.info("Stopped stream: %s", self.source)
_LOGGER.info(
"Stopped stream: %s", STREAM_SOURCE_RE.sub("//", str(self.source))
)
async def async_record(self, video_path, duration=30, lookback=5):
"""Make a .mp4 recording from a provided stream."""

View File

@ -5,6 +5,7 @@ import logging
import av
from . import STREAM_SOURCE_RE
from .const import (
AUDIO_CODECS,
MAX_MISSING_DTS,
@ -127,7 +128,9 @@ def stream_worker(source, options, segment_buffer, quit_event):
try:
container = av.open(source, options=options, timeout=STREAM_TIMEOUT)
except av.AVError:
_LOGGER.error("Error opening stream %s", source)
_LOGGER.error(
"Error opening stream %s", STREAM_SOURCE_RE.sub("//", str(source))
)
return
try:
video_stream = container.streams.video[0]

View File

@ -257,3 +257,13 @@ async def test_record_stream_audio(
# Verify that the save worker was invoked, then block until its
# thread completes and is shutdown completely to avoid thread leaks.
await record_worker_sync.join()
async def test_recorder_log(hass, caplog):
"""Test starting a stream to record logs the url without username and password."""
await async_setup_component(hass, "stream", {"stream": {}})
stream = create_stream(hass, "https://abcd:efgh@foo.bar")
with patch.object(hass.config, "is_allowed_path", return_value=True):
await stream.async_record("/example/path")
assert "https://abcd:efgh@foo.bar" not in caplog.text
assert "https://foo.bar" in caplog.text

View File

@ -574,3 +574,18 @@ async def test_update_stream_source(hass):
# Ccleanup
stream.stop()
async def test_worker_log(hass, caplog):
"""Test that the worker logs the url without username and password."""
stream = Stream(hass, "https://abcd:efgh@foo.bar")
stream.add_provider(STREAM_OUTPUT_FORMAT)
with patch("av.open") as av_open:
av_open.side_effect = av.error.InvalidDataError(-2, "error")
segment_buffer = SegmentBuffer(stream.outputs)
stream_worker(
"https://abcd:efgh@foo.bar", {}, segment_buffer, threading.Event()
)
await hass.async_block_till_done()
assert "https://abcd:efgh@foo.bar" not in caplog.text
assert "https://foo.bar" in caplog.text