Вендоринг исходников nextcloud-talk-recording в opt/f7cloud-talk-recording-src и уточнение apt-установки

This commit is contained in:
root
2026-03-11 11:28:07 +00:00
parent f1cc04e550
commit cd2a175063
65 changed files with 6258 additions and 17 deletions
@@ -0,0 +1,390 @@
#
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# pylint: disable=missing-docstring
from ipaddress import ip_network
import pytest
from nextcloud.talk.recording.Config import Config
class ConfigTest:
@pytest.fixture
def configLoadedFromString(self, monkeypatch):
# pylint: disable=protected-access
config = Config()
# pylint: disable=unused-argument
def mockRead(fileName):
# pylint: disable=no-member
config._configParser.read_string(config.configString)
monkeypatch.setattr(config._configParser, 'read', mockRead)
return config
def testGetTrustedProxies(self, configLoadedFromString):
configLoadedFromString.configString = """
[app]
trustedproxies = 127.0.0.1, 2001:db8::0, not-an-ip, 192.168.0.0/16, 2001:db8::1234:0/112
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getTrustedProxies() == [
ip_network('127.0.0.1'),
ip_network('2001:db8::0'),
ip_network('192.168.0.0/16'),
ip_network('2001:db8::1234:0/112')
]
def testGetTrustedProxiesWhenCommented(self, configLoadedFromString):
configLoadedFromString.configString = """
[app]
#trustedproxies =
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getTrustedProxies() == []
def testGetTrustedProxiesWhenEmpty(self, configLoadedFromString):
configLoadedFromString.configString = """
[app]
trustedproxies =
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getTrustedProxies() == []
def testGetBackendValuesWhenNotSet(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 1024
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
def testGetBackendValuesWhenSet(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
backends = backend1
skipverify = true
maxmessagesize = 512
videowidth = 960
videoheight = 540
directory = /srv/recording
[backend1]
url = https://cloud.server.com
secret = the-shared-secret
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
backendUrl = 'https://cloud.server.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetBackendValuesWhenSetByBackend(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
backends = backend1
skipverify = false
maxmessagesize = 256
videowidth = 480
videoheight = 270
directory = /tmp/files
[backend1]
url = https://cloud.server.com
secret = the-shared-secret
skipverify = true
maxmessagesize = 512
videowidth = 960
videoheight = 540
directory = /srv/recording
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 256
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 480
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 270
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp/files'
backendUrl = 'https://cloud.server.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetBackendValuesWhenAllowingAll(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
allowall = true
secret = the-shared-secret-common
backends = backend1
[backend1]
url = https://cloud.server.com
secret = the-shared-secret
skipverify = true
maxmessagesize = 512
videowidth = 960
videoheight = 540
directory = /srv/recording
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret-common'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 1024
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
backendUrl = 'https://cloud.server.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret-common'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetBackendValuesWhenExplicitlyDisallowingAll(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
allowall = false
secret = the-shared-secret-common
backends = backend1
[backend1]
url = https://cloud.server.com
secret = the-shared-secret
skipverify = true
maxmessagesize = 512
videowidth = 960
videoheight = 540
directory = /srv/recording
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 1024
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
backendUrl = 'https://cloud.server.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetBackendValuesWhenExplicitlyDisallowingAllWithoutCommonSecret(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
allowall = false
backends = backend1
[backend1]
url = https://cloud.server.com
secret = the-shared-secret
skipverify = true
maxmessagesize = 512
videowidth = 960
videoheight = 540
directory = /srv/recording
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 1024
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
backendUrl = 'https://cloud.server.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is True
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetBackendValuesWhenSeveralBackends(self, configLoadedFromString):
configLoadedFromString.configString = """
[backend]
backends = first-backend, second-backend
maxmessagesize = 2048
[first-backend]
url = https://cloud.server1.com
secret = the-shared-secret1
maxmessagesize = 512
videowidth = 960
videoheight = 540
[second-backend]
url = https://cloud.server2.com
secret = the-shared-secret2
directory = /srv/recording
"""
configLoadedFromString.load('fake-file-name')
backendUrl = 'https://cloud.unknown.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) is None
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 2048
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
backendUrl = 'https://cloud.server1.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret1'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 512
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 960
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 540
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/tmp'
backendUrl = 'https://cloud.server2.com/'
assert configLoadedFromString.getBackendSecret(backendUrl) == 'the-shared-secret2'
assert configLoadedFromString.getBackendSkipVerify(backendUrl) is False
assert configLoadedFromString.getBackendMaximumMessageSize(backendUrl) == 2048
assert configLoadedFromString.getBackendVideoWidth(backendUrl) == 1920
assert configLoadedFromString.getBackendVideoHeight(backendUrl) == 1080
assert configLoadedFromString.getBackendDirectory(backendUrl) == '/srv/recording'
def testGetSignalingSecretWhenNotSet(self, configLoadedFromString):
configLoadedFromString.configString = """
[signaling]
"""
configLoadedFromString.load('fake-file-name')
signalingUrl = 'https://signaling.unknown.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) is None
def testGetSignalingSecretWhenSet(self, configLoadedFromString):
configLoadedFromString.configString = """
[signaling]
internalsecret = the-internal-secret-common
signalings = signaling1
[signaling1]
url = https://signaling.server.com
"""
configLoadedFromString.load('fake-file-name')
signalingUrl = 'https://signaling.unknown.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret-common'
signalingUrl = 'https://signaling.server.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret-common'
def testGetSignalingSecretWhenSetBySignaling(self, configLoadedFromString):
configLoadedFromString.configString = """
[signaling]
signalings = signaling1
[signaling1]
url = https://signaling.server.com
internalsecret = the-internal-secret
"""
configLoadedFromString.load('fake-file-name')
signalingUrl = 'https://signaling.unknown.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) is None
signalingUrl = 'https://signaling.server.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret'
def testGetSignalingSecretWhenSeveralSignalings(self, configLoadedFromString):
configLoadedFromString.configString = """
[signaling]
internalsecret = the-internal-secret-common
signalings = signaling1, signaling2
[signaling1]
url = https://signaling.server1.com
internalsecret = the-internal-secret1
[signaling2]
url = https://signaling.server2.com
internalsecret = the-internal-secret2
"""
configLoadedFromString.load('fake-file-name')
signalingUrl = 'https://signaling.unknown.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret-common'
signalingUrl = 'https://signaling.server1.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret1'
signalingUrl = 'https://signaling.server2.com'
assert configLoadedFromString.getSignalingSecret(signalingUrl) == 'the-internal-secret2'
def testGetStatsAllowedIps(self, configLoadedFromString):
configLoadedFromString.configString = """
[stats]
allowed_ips = 127.0.0.1, 2001:db8::0, not-an-ip, 192.168.0.0/16, 2001:db8::1234:0/112
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getStatsAllowedIps() == [
ip_network('127.0.0.1'),
ip_network('2001:db8::0'),
ip_network('192.168.0.0/16'),
ip_network('2001:db8::1234:0/112')
]
def testGetStatsAllowedIpsWhenCommented(self, configLoadedFromString):
configLoadedFromString.configString = """
[stats]
#allowed_ips =
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getStatsAllowedIps() == [
ip_network('127.0.0.1')
]
def testGetStatsAllowedIpsWhenEmpty(self, configLoadedFromString):
configLoadedFromString.configString = """
[stats]
allowed_ips =
"""
configLoadedFromString.load('fake-file-name')
assert configLoadedFromString.getStatsAllowedIps() == []
@@ -0,0 +1,414 @@
#
# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# pylint: disable=missing-docstring
import sys
from ipaddress import ip_address, ip_network
import pytest
# pulsectl tries to load the PulseAudio library on initialization, so a fake
# module is set instead to prevent a failure when (indirectly) importing it if
# the library is not installed in the system.
sys.modules['pulsectl'] = {}
# pylint: disable=wrong-import-position
from nextcloud.talk.recording.Server import isAddressInNetworks, TrustedProxiesFix
@pytest.mark.parametrize('address, networks, expectedResult', [
('192.168.57.42', [], False),
('192.168.57.42', ['192.168.58.0/24'], False),
('192.168.57.42', ['192.168.57.0/24'], True),
('2001:db8::abc', [], False),
('2001:db8::abc', ['2001:db8::b00/120'], False),
('2001:db8::abc', ['2001:db8::a00/120'], True),
('192.168.57.42', ['192.168.58.0/24', '2001:db8::a00/120', '192.168.57.42', '2001:db8::b00/120'], True),
('192.168.59.42', ['192.168.58.0/24', '2001:db8::a00/120', '192.168.57.42', '2001:db8::b00/120'], False),
('2001:db8::abc', ['192.168.58.0/24', '2001:db8::a00/120', '192.168.57.42', '2001:db8::b00/120'], True),
('2001:db8::cbc', ['192.168.58.0/24', '2001:db8::a00/120', '192.168.57.42', '2001:db8::b00/120'], False),
])
def testIsAddressInNetworks(address, networks, expectedResult):
address = ip_address(address)
networks = [ip_network(network) for network in networks]
assert isAddressInNetworks(address, networks) == expectedResult
class TrustedProxiesFixTest:
@pytest.fixture
def fakeConfig(self):
class FakeConfig:
def __init__(self):
self.trustedProxies = []
def getTrustedProxies(self):
return self.trustedProxies
return FakeConfig()
@pytest.mark.parametrize('remoteAddress, xForwardedFor, trustedProxies, expectedRemoteAddress', [
# No trusted proxy
(
'4.8.15.16',
'',
'',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0',
'',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'',
'4.8.15.16'
),
(
'4.8.15.16:12345',
'',
'',
'4.8.15.16:12345'
),
(
'2001:db8:4815::16',
'',
'',
'2001:db8:4815::16'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108',
'',
'2001:db8:4815::16'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108, 2001:db8:1011::1213',
'',
'2001:db8:4815::16'
),
(
'[2001:db8:4815::16]:12345',
'',
'',
'[2001:db8:4815::16]:12345'
),
(
'4.8.15.16',
'2001:db8:2342::108',
'',
'4.8.15.16'
),
(
'2001:db8:4815::16',
'23.42.108.0',
'',
'2001:db8:4815::16'
),
# Trusted proxy not matching remote address
(
'4.8.15.16',
'',
'10.11.12.13',
'4.8.15.16'
),
(
'4.8.15.16',
'10.11.12.13',
'10.11.12.13',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0',
'10.11.12.13',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'10.11.12.13',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'4.8.16.0/24, 10.11.12.13',
'4.8.15.16'
),
(
'4.8.15.16:12345',
'',
'10.11.12.13',
'4.8.15.16:12345'
),
(
'2001:db8:4815::16',
'2001:db8:1011::1213',
'2001:db8:1011::1213',
'2001:db8:4815::16'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108, 2001:db8:1011::1213',
'2001:db8:4816::0/48, 2001:db8:1011::1213',
'2001:db8:4815::16'
),
(
'[2001:db8:4815::16]:12345',
'2001:db8:1011::1213',
'2001:db8:1011::1213',
'[2001:db8:4815::16]:12345'
),
(
'4.8.15.16',
'23.42.108.0, 2001:db8:1011::1213',
'2001:db8:1011::1213',
'4.8.15.16'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108, 10.11.12.13',
'10.11.12.13',
'2001:db8:4815::16'
),
# Trusted proxy matching remote address
(
'4.8.15.16',
'',
'4.8.15.16',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0',
'4.8.15.16',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0',
'4.8.15.0/24',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0',
'10.11.12.13, 4.8.15.0/24',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0',
'10.11.12.13, 4.8.15.0/24, 10.11.12.14',
'23.42.108.0'
),
(
'4.8.15.16',
'10.11.12.13, 23.42.108.0',
'4.8.15.16',
'23.42.108.0'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108',
'2001:db8:4815::16',
'2001:db8:2342::108'
),
(
'4.8.15.16',
'2001:db8:2342::108',
'4.8.15.0/24',
'2001:db8:2342::108'
),
(
'2001:db8:4815::16',
'23.42.108.0',
'2001:db8:4815::0/112',
'23.42.108.0'
),
# Trusted proxy matching remote address and forwarded header
(
'4.8.15.16',
'23.42.108.0',
'4.8.15.16, 23.42.108.0',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0, 4.8.15.108',
'4.8.15.0/24',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'4.8.15.16, 10.11.12.13',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'10.11.12.13, 4.8.15.16',
'23.42.108.0'
),
(
'4.8.15.16',
'10.11.12.13, 23.42.108.0',
'4.8.15.16, 10.11.12.13',
'23.42.108.0'
),
(
'4.8.15.16',
'23.42.108.0, 10.11.12.13',
'4.8.15.16, 10.11.12.0/24',
'23.42.108.0'
),
(
'4.8.15.16',
'10.11.12.15, 23.42.108.0, 10.11.12.14, 10.11.12.13',
'4.8.15.16, 10.11.12.0/24',
'23.42.108.0'
),
(
'4.8.15.16',
'10.11.12.15, 23.42.108.0, 10.11.12.14, 10.11.12.13',
'4.8.15.16, 10.11.12.13, 10.11.12.14, 10.11.12.15',
'23.42.108.0'
),
(
'4.8.15.16:12345',
'10.11.12.15:23456, 23.42.108.0:34567, 10.11.12.14:45678, 10.11.12.13:56789',
'4.8.15.16, 10.11.12.13, 10.11.12.14, 10.11.12.15',
'23.42.108.0'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108',
'2001:db8:4815::16, 2001:db8:2342::108',
'2001:db8:2342::108'
),
(
'2001:db8:4815::16',
'2001:db8:1011::1215, 2001:db8:2342::108, 2001:db8:1011::1214, 2001:db8:1011::1213',
'2001:db8:1011::0/48, 2001:db8:4815::16',
'2001:db8:2342::108'
),
(
'4.8.15.16',
'10.11.12.15, 2001:db8:2342::108, 10.11.12.14, 2001:db8:1011::1213',
'2001:db8:1011::0/48, 4.8.15.16, 10.11.12.14',
'2001:db8:2342::108'
),
(
'2001:db8:4815::16',
'10.11.12.15, 23.42.108.0, 2001:db8:1011::1214, 10.11.12.13',
'10.11.12.13, 2001:db8::0/32',
'23.42.108.0'
),
(
'[2001:db8:4815::16]:12345',
'10.11.12.15:23456, 23.42.108.0:34567, [2001:db8:1112::1314], [2001:db8:1011::1214]:45678, 10.11.12.13:56789',
'10.11.12.13, 2001:db8::0/32',
'23.42.108.0'
),
# Invalid IP in forwarded header
(
'4.8.15.16',
'not-an-ip',
'4.8.15.0/24',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0, not-an-ip',
'4.8.15.0/24',
'4.8.15.16'
),
(
'4.8.15.16',
'23.42.108.0, not-an-ip, 4.8.15.108',
'4.8.15.0/24',
'4.8.15.108'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108, not-an-ip, 2001:db8:4815::108',
'2001:db8:4815::0/112',
'2001:db8:4815::108'
),
(
'4.8.15.16',
'23.42.108.0, not-an-ip, 2001:db8:4815::108',
'4.8.15.16, 2001:db8:4815::108',
'2001:db8:4815::108'
),
(
'2001:db8:4815::16',
'2001:db8:2342::108, not-an-ip, 4.8.15.108',
'2001:db8:4815::16, 4.8.15.108',
'4.8.15.108'
),
(
'2001:db8:4815::16',
',,not-an-ip,,2001:db8:2342::108,,, , 4.8.15.108 ',
'2001:db8:4815::16, 4.8.15.108',
'4.8.15.108'
),
])
def testGetRemoteAddress(self, fakeConfig, remoteAddress, xForwardedFor, trustedProxies, expectedRemoteAddress):
environment = {
'REMOTE_ADDR': remoteAddress,
}
if xForwardedFor:
environment['HTTP_X_FORWARDED_FOR'] = xForwardedFor
trustedProxies = [ip_network(trustedProxy.strip()) for trustedProxy in trustedProxies.split(',') if trustedProxy]
fakeConfig.trustedProxies = trustedProxies
trustedProxiesFix = TrustedProxiesFix(None, fakeConfig)
assert trustedProxiesFix.getRemoteAddress(environment) == expectedRemoteAddress
def testGetRemoteAddressWithoutOriginalRemoteAddress(self, fakeConfig):
trustedProxiesFix = TrustedProxiesFix(None, fakeConfig)
with pytest.raises(ValueError):
trustedProxiesFix.getRemoteAddress({})
def testGetRemoteAddressWithEmptyOriginalRemoteAddress(self, fakeConfig):
trustedProxiesFix = TrustedProxiesFix(None, fakeConfig)
with pytest.raises(ValueError):
trustedProxiesFix.getRemoteAddress({
'REMOTE_ADDR': '',
})
@pytest.mark.parametrize('address, expectedAddress', [
('192.168.0.42', '192.168.0.42'),
('192.168.0.42:12345', '192.168.0.42'),
('::1', '::1'),
('2001:db8::0', '2001:db8::0'),
('2001:0db8:1234:5678:90ab:cdef:1234:5678', '2001:0db8:1234:5678:90ab:cdef:1234:5678'),
('[::1]', '::1'),
('[2001:db8::0]', '2001:db8::0'),
('[2001:0db8:1234:5678:90ab:cdef:1234:5678]', '2001:0db8:1234:5678:90ab:cdef:1234:5678'),
('[::1]:12345', '::1'),
('[2001:db8::0]:12345', '2001:db8::0'),
('[2001:0db8:1234:5678:90ab:cdef:1234:5678]:12345', '2001:0db8:1234:5678:90ab:cdef:1234:5678'),
('not-an-ip', 'not-an-ip'),
('not-an-ip:at-all', 'not-an-ip'),
('not:an:ip::at-all', 'not:an:ip::at-all'),
('[not:an:ip][very][::weird]', 'not:an:ip][very][::weird'),
])
def testGetAddressWithoutPort(self, fakeConfig, address, expectedAddress):
trustedProxiesFix = TrustedProxiesFix(None, fakeConfig)
# pylint: disable=protected-access
assert trustedProxiesFix._getAddressWithoutPort(address) == expectedAddress