Skip to content

Commit

Permalink
salt: Add a module function to list listening process
Browse files Browse the repository at this point in the history
Add a simple salt function that use `psutil` to list all listening
processes on every ports

Sees: #3092
  • Loading branch information
TeddyAndrieux committed Mar 4, 2021
1 parent 554a9a3 commit 3782e6d
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 0 deletions.
45 changes: 45 additions & 0 deletions salt/_modules/metalk8s_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import itertools
import logging

# Note: psutil is a dependency of Salt RPMs in MetalK8s context we
# always use RPMs to install Salt
import psutil # pylint: disable=3rd-party-module-not-gated

from salt._compat import ipaddress
from salt.exceptions import CommandExecutionError

Expand Down Expand Up @@ -122,3 +126,44 @@ def get_mtu_from_ip(ip):
)

return int(__salt__["file.read"]("/sys/class/net/{}/mtu".format(iface)))


def get_listening_processes():
"""
Get all the listening processes on the local node
Output:
```
{
<port>: {
'<ip>': {
'pid': <pid>,
'name': '<process_name>'
}
}
}
```
"""
all_listen_connections = {}
for sconn in psutil.net_connections("inet"):
if sconn.status != psutil.CONN_LISTEN:
continue

ip, port = sconn.laddr
# If `<ip>` is `::1` replace with `127.0.0.1` so that we consider only IPv4
if ip == "::1":
ip = "127.0.0.1"
# If `<ip>` is `::` replace with `0.0.0.0` so that we consider only IPv4
elif ip == "::":
ip = "0.0.0.0"

all_listen_connections.setdefault(port, {}).update(
{
ip: {
"pid": sconn.pid,
"name": psutil.Process(sconn.pid).name(),
}
}
)

return all_listen_connections
1 change: 1 addition & 0 deletions salt/tests/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ etcd3 != 0.11.0
kubernetes
urllib3
pyfakefs
psutil
30 changes: 30 additions & 0 deletions salt/tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,36 @@ protobuf==3.15.3 \
--hash=sha256:f9aa4c216e48236c6af4e71f64afc0c13c12401d3067a323b9fe543bb676bac3 \
--hash=sha256:ffc556af23c7e1278b43719999dd215619f73f8d42f40275c55a1de09938214f \
# via etcd3
psutil==5.8.0 \
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563 \
# via -r salt/tests/requirements.in
py==1.10.0 \
--hash=sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3 \
--hash=sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a \
Expand Down
39 changes: 39 additions & 0 deletions salt/tests/unit/modules/files/test_metalk8s_network.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
get_listening_processes:
- result: {}
- net_conns_ret:
# `::` will be replaced with `0.0.0.0`
- laddr: ["::", 6443]
pid: 111
# `::1` will be replaced with `127.0.0.1`
- laddr: ["::1", 456]
pid: 123
- laddr: ["1.2.3.4", 123]
pid: 222
- laddr: ["2.3.4.5", 123]
pid: 333
# Ignored as status != LISTEN
- laddr: ["127.0.0.1", 12345]
status: ESTABILISHED
pid: 456
process_ret:
111: apiserver
123: likely-something
222: my-process
333: my-second-process
456: do-we-care
result:
123:
1.2.3.4:
pid: 222
name: my-process
2.3.4.5:
pid: 333
name: my-second-process
6443:
0.0.0.0:
pid: 111
name: apiserver
456:
127.0.0.1:
pid: 123
name: likely-something
38 changes: 38 additions & 0 deletions salt/tests/unit/modules/test_metalk8s_network.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import os.path
from unittest import TestCase
from unittest.mock import MagicMock, patch

from parameterized import parameterized
from salt.exceptions import CommandExecutionError
import yaml

import metalk8s_network

from tests.unit import mixins
from tests.unit import utils


YAML_TESTS_FILE = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "files", "test_metalk8s_network.yaml"
)
with open(YAML_TESTS_FILE) as fd:
YAML_TESTS_CASES = yaml.safe_load(fd)


class Metalk8sNetworkTestCase(TestCase, mixins.LoaderModuleMockMixin):
Expand Down Expand Up @@ -228,3 +238,31 @@ def _read_mtu_file(path):
self.assertEqual(
result, metalk8s_network.get_mtu_from_ip("10.200.0.42")
)

@utils.parameterized_from_cases(YAML_TESTS_CASES["get_listening_processes"])
def test_get_listening_processes(
self, result, net_conns_ret=None, process_ret=None
):
"""
Tests the return of `get_listening_processes` function
"""
net_conns_return = []
for net_conn in net_conns_ret or []:
sconn_mock = MagicMock()
sconn_mock.status = net_conn.get("status", "LISTEN")
sconn_mock.laddr = net_conn.get("laddr")
sconn_mock.pid = net_conn.get("pid")
net_conns_return.append(sconn_mock)

process_return = {}
for pid, name in (process_ret or {}).items():
process_return[pid] = MagicMock()
process_return[pid].name.return_value = name

net_conns_mock = MagicMock(return_value=net_conns_return)
process_mock = MagicMock(side_effect=process_return.get)

with patch("psutil.net_connections", net_conns_mock), patch(
"psutil.Process", process_mock
):
self.assertEqual(metalk8s_network.get_listening_processes(), result)

0 comments on commit 3782e6d

Please sign in to comment.