Skip to content

Commit

Permalink
Add a workaround around non-ascii and non-standard FQDNs (#790)
Browse files Browse the repository at this point in the history
Add a wrapper around `socket.getfqdn()` which returns `invalid.hostname`
in cases where hostname, or rather FQDN contains non-ascii and
non-standard characters.

This works around the issue that non-ascii characters can't be inserted
into leapp database.

For the standard for hostnames see `hostname(7)`. The current
implementation doesn't check for length of hostname nor it's individual
segments.
  • Loading branch information
matejmatuska authored Aug 23, 2022
1 parent 649025b commit 1cbb4b9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 0 deletions.
2 changes: 2 additions & 0 deletions leapp/utils/workarounds/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import leapp.utils.workarounds.mp
import leapp.utils.workarounds.fqdn


def apply_workarounds():
leapp.utils.workarounds.mp.apply_workaround()
leapp.utils.workarounds.fqdn.apply_workaround()
18 changes: 18 additions & 0 deletions leapp/utils/workarounds/fqdn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import re
import socket


def decorate_getfqdn(fn):
def wrap(*args, **kwargs):
result = fn(*args, **kwargs)
# check whether FQDN conforms to standard, see HOSTNAME(7)
pattern = r"^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$"
if re.match(pattern, result, re.IGNORECASE):
return result
return 'invalid.hostname'

return wrap


def apply_workaround():
setattr(socket, 'getfqdn', decorate_getfqdn(socket.getfqdn))
25 changes: 25 additions & 0 deletions tests/scripts/test_workarounds_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from multiprocessing import util, Process, Manager

import os
import pytest

import leapp # noqa: F401; pylint: disable=unused-import
from leapp.utils.workarounds import fqdn


def test_mp_is_patched():
Expand All @@ -29,3 +31,26 @@ def child_fun(_lst):
def test_mp_workaround_applied():
if getattr(util, 'os', None) is None:
assert util.Finalize.__name__ == 'FixedFinalize'


@pytest.mark.parametrize(
('input_fqdn', 'valid'),
[
('foo.bar.com', True),
('foo\xa0bar.foo.com', False),
('-foo.bar', False),
('foo.bar-', False),
('foo.-bar.1234', False),
('a1.b2.c3', True),
('123.foo.bar', True),
('123.f-o-o.b-a-r', True),
]
)
def test_fqdn_is_patched(input_fqdn, valid):

def getfqdn():
return input_fqdn

fn = fqdn.decorate_getfqdn(getfqdn)
expected_fqdn = input_fqdn if valid else 'invalid.hostname'
assert fn() == expected_fqdn

0 comments on commit 1cbb4b9

Please sign in to comment.