Skip to content

Commit

Permalink
python tests: compatibility and stability improvements
Browse files Browse the repository at this point in the history
This commit improves the compatibility and stability of Python tests
for Filebeat. It addresses two main probmes:
1. Some deprecated TLS functions are now raising deprecation
exceptions (since Python 3.10.0)
2. Some tests, on failure, leave Filebeat running and bound to port
8080, this creates a cascading failure of the subsequent tests that
require the same port to be available.

The main changes are:
 - Ensuring Filebeat process is always terminated, even if the test
 fails
 - Using the replacement methods/objects for the deprecated TLS
 functions.
  • Loading branch information
belimawr committed May 12, 2022
1 parent 6be376e commit 4989ce0
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-developer.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ The list below covers the major changes between 7.0.0-rc2 and main only.
- Add gcp dataproc metricset. {pull}30008[30008]
- Add Github action for linting
- Add regex support for drop_fields processor.
- Improve compatibility and reduce flakyness of Python tests {pull}31588[31588]

==== Deprecated

Expand Down
5 changes: 5 additions & 0 deletions filebeat/tests/system/test_syslog.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def test_syslog_with_tcp(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains("Start accepting connections"))

Expand Down Expand Up @@ -72,6 +73,7 @@ def test_syslog_with_tcp_invalid_message(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains("Start accepting connections"))

Expand Down Expand Up @@ -112,6 +114,7 @@ def test_syslog_with_udp(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains("Started listening for UDP connection"))

Expand Down Expand Up @@ -172,6 +175,7 @@ def run_filebeat_and_send_using_socket(self, socket_type, send_over_socket):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

if socket_type == "stream":
self.wait_until(lambda: self.log_contains("Start accepting connections"))
Expand Down Expand Up @@ -235,6 +239,7 @@ def run_filebeat_and_send_invalid_message_using_socket(self, socket_type, send_o
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

if socket_type == "stream":
self.wait_until(lambda: self.log_contains("Start accepting connections"))
Expand Down
38 changes: 29 additions & 9 deletions filebeat/tests/system/test_tcp_tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,18 @@ def test_tcp_over_tls_and_verify_valid_server_without_mutual_auth(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
tls = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED,
ca_certs=CERTIFICATE1, do_handshake_on_connect=True)
context = ssl.create_default_context()
context.load_verify_locations(cafile=CERTIFICATE1)
context.options = ssl.CERT_REQUIRED
context.check_hostname = False

tls = context.wrap_socket(sock, do_handshake_on_connect=True)
tls.connect((config.get('host'), config.get('port')))

for n in range(0, NUMBER_OF_EVENTS):
Expand Down Expand Up @@ -116,14 +121,18 @@ def test_tcp_over_tls_and_verify_invalid_server_without_mutual_auth(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
tls = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED,
ca_certs=CERTIFICATE2, do_handshake_on_connect=True)
context = ssl.create_default_context()
context.load_verify_locations(capath=CERTIFICATE2)
context.options = ssl.CERT_REQUIRED
context.check_hostname = False

tls = context.wrap_socket(sock, do_handshake_on_connect=True, server_hostname=None)
with pytest.raises(ssl.SSLError):
tls.connect((config.get('host'), config.get('port')))

Expand Down Expand Up @@ -157,13 +166,19 @@ def test_tcp_over_tls_mutual_auth_fails(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tls = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED,
ca_certs=CERTIFICATE1, do_handshake_on_connect=True)

context = ssl.create_default_context()
context.load_verify_locations(capath=CERTIFICATE1)
context.options = ssl.CERT_REQUIRED
context.check_hostname = False

tls = context.wrap_socket(sock, do_handshake_on_connect=True, server_hostname=None)

with pytest.raises(ssl.SSLError):
tls.connect((config.get('host'), config.get('port')))
Expand Down Expand Up @@ -204,16 +219,18 @@ def test_tcp_over_tls_mutual_auth_succeed(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(CACERT)
context.load_cert_chain(certfile=CLIENT2, keyfile=CLIENTKEY2)
context.check_hostname = False

tls = context.wrap_socket(sock, server_side=False)

Expand Down Expand Up @@ -262,6 +279,7 @@ def test_tcp_tls_with_a_plain_text_socket(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))
Expand Down Expand Up @@ -315,18 +333,20 @@ def test_tcp_over_tls_mutual_auth_rfc6587_framing(self):
)

filebeat = self.start_beat()
self.addCleanup(filebeat.kill_and_wait)

self.wait_until(lambda: self.log_contains(
"Start accepting connections"))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(CACERT)
context.load_cert_chain(certfile=CLIENT2, keyfile=CLIENTKEY2)
context.check_hostname = False

tls = context.wrap_socket(sock, server_side=False)
tls = context.wrap_socket(sock)

tls.connect((config.get('host'), config.get('port')))

Expand Down
9 changes: 7 additions & 2 deletions libbeat/tests/system/beat/beat.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,11 @@ def kill_and_wait(self):
"""
kill_and_wait will kill the process and wait for it to return
"""
self.kill()
os.close(self.stdin_write)
# If the process is running, kill it and close self.stdin_write
# this is done so this method can safely be called multiple times
if self.proc.poll() is None:
self.kill()
os.close(self.stdin_write)
return self.wait()

def check_kill_and_wait(self, exit_code=0):
Expand All @@ -151,6 +154,8 @@ def check_kill_and_wait(self, exit_code=0):

def __del__(self):
# Ensure the process is stopped.
# For some reason when some tests error/timeout this
# method is not called in a timely manner.
try:
self.proc.terminate()
self.proc.kill()
Expand Down

0 comments on commit 4989ce0

Please sign in to comment.