mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
fix: Enable port modification in state selinux.port_policy_present
This commit is contained in:
parent
b990868ca7
commit
0512a8a52a
3 changed files with 391 additions and 19 deletions
|
@ -10,7 +10,6 @@ Execute calls on selinux
|
|||
proper packages are installed.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
@ -807,12 +806,47 @@ def port_add_policy(name, sel_type=None, protocol=None, port=None, sel_range=Non
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' selinux.port_add_policy add tcp/8080 http_port_t
|
||||
salt '*' selinux.port_add_policy add foobar http_port_t protocol=tcp port=8091
|
||||
salt '*' selinux.port_add_policy tcp/8080 http_port_t
|
||||
salt '*' selinux.port_add_policy foobar http_port_t protocol=tcp port=8091
|
||||
"""
|
||||
return _port_add_or_delete_policy("add", name, sel_type, protocol, port, sel_range)
|
||||
|
||||
|
||||
def port_modify_policy(name, sel_type=None, protocol=None, port=None, sel_range=None):
|
||||
"""
|
||||
.. versionadded:: 2019.2.0
|
||||
|
||||
Modifies the SELinux policy for a given protocol and port.
|
||||
|
||||
Returns the result of the call to semanage.
|
||||
|
||||
name
|
||||
The protocol and port spec. Can be formatted as ``(tcp|udp)/(port|port-range)``.
|
||||
|
||||
sel_type
|
||||
The SELinux Type. Required.
|
||||
|
||||
protocol
|
||||
The protocol for the port, ``tcp`` or ``udp``. Required if name is not formatted.
|
||||
|
||||
port
|
||||
The port or port range. Required if name is not formatted.
|
||||
|
||||
sel_range
|
||||
The SELinux MLS/MCS Security Range.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' selinux.port_modify_policy tcp/8080 http_port_t
|
||||
salt '*' selinux.port_modify_policy foobar http_port_t protocol=tcp port=8091
|
||||
"""
|
||||
return _port_add_or_delete_policy(
|
||||
"modify", name, sel_type, protocol, port, sel_range
|
||||
)
|
||||
|
||||
|
||||
def port_delete_policy(name, protocol=None, port=None):
|
||||
"""
|
||||
.. versionadded:: 2019.2.0
|
||||
|
@ -846,13 +880,13 @@ def _port_add_or_delete_policy(
|
|||
"""
|
||||
.. versionadded:: 2019.2.0
|
||||
|
||||
Performs the action as called from ``port_add_policy`` or ``port_delete_policy``.
|
||||
Performs the action as called from ``port_add_policy``, ``port_modify_policy`` or ``port_delete_policy``.
|
||||
|
||||
Returns the result of the call to semanage.
|
||||
"""
|
||||
if action not in ["add", "delete"]:
|
||||
if action not in ["add", "modify", "delete"]:
|
||||
raise SaltInvocationError(
|
||||
f'Actions supported are "add" and "delete", not "{action}".'
|
||||
f'Actions supported are "add", "modify" and "delete", not "{action}".'
|
||||
)
|
||||
if action == "add" and not sel_type:
|
||||
raise SaltInvocationError("SELinux Type is required to add a policy")
|
||||
|
|
|
@ -464,10 +464,8 @@ def fcontext_policy_applied(name, recursive=False):
|
|||
ret.update(
|
||||
{
|
||||
"result": True,
|
||||
"comment": (
|
||||
'SElinux policies are already applied for filespec "{}"'.format(
|
||||
name
|
||||
)
|
||||
"comment": 'SElinux policies are already applied for filespec "{}"'.format(
|
||||
name
|
||||
),
|
||||
}
|
||||
)
|
||||
|
@ -517,24 +515,31 @@ def port_policy_present(name, sel_type, protocol=None, port=None, sel_range=None
|
|||
{
|
||||
"result": True,
|
||||
"comment": f'SELinux policy for "{name}" already present '
|
||||
+ 'with specified sel_type "{}", protocol "{}" and port "{}".'.format(
|
||||
sel_type, protocol, port
|
||||
),
|
||||
+ f'with specified sel_type "{sel_type}", protocol "{protocol}" and port "{port}".',
|
||||
}
|
||||
)
|
||||
return ret
|
||||
if __opts__["test"]:
|
||||
ret.update({"result": None})
|
||||
else:
|
||||
add_ret = __salt__["selinux.port_add_policy"](
|
||||
old_state = __salt__["selinux.port_get_policy"](
|
||||
name=name,
|
||||
protocol=protocol,
|
||||
port=port,
|
||||
)
|
||||
if old_state:
|
||||
module_method = "selinux.port_modify_policy"
|
||||
else:
|
||||
module_method = "selinux.port_add_policy"
|
||||
add_modify_ret = __salt__[module_method](
|
||||
name=name,
|
||||
sel_type=sel_type,
|
||||
protocol=protocol,
|
||||
port=port,
|
||||
sel_range=sel_range,
|
||||
)
|
||||
if add_ret["retcode"] != 0:
|
||||
ret.update({"comment": f"Error adding new policy: {add_ret}"})
|
||||
if add_modify_ret["retcode"] != 0:
|
||||
ret.update({"comment": f"Error adding new policy: {add_modify_ret}"})
|
||||
else:
|
||||
ret.update({"result": True})
|
||||
new_state = __salt__["selinux.port_get_policy"](
|
||||
|
@ -578,9 +583,7 @@ def port_policy_absent(name, sel_type=None, protocol=None, port=None):
|
|||
{
|
||||
"result": True,
|
||||
"comment": f'SELinux policy for "{name}" already absent '
|
||||
+ 'with specified sel_type "{}", protocol "{}" and port "{}".'.format(
|
||||
sel_type, protocol, port
|
||||
),
|
||||
+ f'with specified sel_type "{sel_type}", protocol "{protocol}" and port "{port}".',
|
||||
}
|
||||
)
|
||||
return ret
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""
|
||||
:codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
|
||||
:codeauthor: Jason Woods <devel@jasonwoods.me.uk>
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
@ -118,3 +119,337 @@ def test_boolean():
|
|||
ret.update({"comment": comt, "result": False})
|
||||
ret.update({"changes": {}})
|
||||
assert selinux.boolean(name, value) == ret
|
||||
|
||||
|
||||
def test_port_policy_present():
|
||||
"""
|
||||
Test to set up an SELinux port.
|
||||
"""
|
||||
name = "tcp/8080"
|
||||
protocol = "tcp"
|
||||
port = "8080"
|
||||
ret = {"name": name, "changes": {}, "result": False, "comment": ""}
|
||||
|
||||
# Test when already present with same sel_type
|
||||
mock_add = MagicMock(return_value={"retcode": 0})
|
||||
mock_modify = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
return_value={
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
}
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_add_policy": mock_add,
|
||||
"selinux.port_modify_policy": mock_modify,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
comt = (
|
||||
f'SELinux policy for "{name}" already present '
|
||||
+ f'with specified sel_type "http_cache_port_t", protocol "None" '
|
||||
+ f'and port "None".'
|
||||
)
|
||||
ret.update({"comment": comt, "result": True})
|
||||
assert selinux.port_policy_present(name, "http_cache_port_t") == ret
|
||||
|
||||
comt = (
|
||||
f'SELinux policy for "name" already present '
|
||||
+ f'with specified sel_type "http_cache_port_t", protocol "{protocol}" '
|
||||
+ f'and port "{port}".'
|
||||
)
|
||||
ret.update({"comment": comt, "changes": {}, "result": True, "name": "name"})
|
||||
assert (
|
||||
selinux.port_policy_present("name", "http_cache_port_t", protocol, port)
|
||||
== ret
|
||||
)
|
||||
ret.update({"name": name})
|
||||
|
||||
# Test adding new port policy
|
||||
mock_add = MagicMock(return_value={"retcode": 0})
|
||||
mock_modify = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
side_effect=[
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8080"},
|
||||
]
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_add_policy": mock_add,
|
||||
"selinux.port_modify_policy": mock_modify,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": True}):
|
||||
ret.update({"comment": "", "result": None})
|
||||
assert selinux.port_policy_present(name, "http_cache_port_t") == ret
|
||||
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
ret.update(
|
||||
{
|
||||
"comment": "",
|
||||
"changes": {
|
||||
"old": None,
|
||||
"new": {
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
},
|
||||
},
|
||||
"result": True,
|
||||
}
|
||||
)
|
||||
assert selinux.port_policy_present(name, "http_cache_port_t") == ret
|
||||
|
||||
# Test modifying policy to a new sel_type
|
||||
mock_add = MagicMock(return_value={"retcode": 0})
|
||||
mock_modify = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
side_effect=[
|
||||
None,
|
||||
None,
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8080"},
|
||||
{"sel_type": "http_port_t", "protocol": "tcp", "port": "8080"},
|
||||
]
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_add_policy": mock_add,
|
||||
"selinux.port_modify_policy": mock_modify,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": True}):
|
||||
ret.update({"comment": "", "changes": {}, "result": None})
|
||||
assert selinux.port_policy_present(name, "http_port_t") == ret
|
||||
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
ret.update(
|
||||
{
|
||||
"comment": "",
|
||||
"changes": {
|
||||
"old": {
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
},
|
||||
"new": {
|
||||
"sel_type": "http_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
},
|
||||
},
|
||||
"result": True,
|
||||
}
|
||||
)
|
||||
assert selinux.port_policy_present(name, "http_port_t") == ret
|
||||
|
||||
# Test adding new port policy with custom name and using protocol and port parameters
|
||||
mock_add = MagicMock(return_value={"retcode": 0})
|
||||
mock_modify = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
side_effect=[
|
||||
None,
|
||||
None,
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8081"},
|
||||
]
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_add_policy": mock_add,
|
||||
"selinux.port_modify_policy": mock_modify,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
ret.update(
|
||||
{
|
||||
"name": "required_protocol_port",
|
||||
"comment": "",
|
||||
"changes": {
|
||||
"old": None,
|
||||
"new": {
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8081",
|
||||
},
|
||||
},
|
||||
"result": True,
|
||||
}
|
||||
)
|
||||
assert (
|
||||
selinux.port_policy_present(
|
||||
"required_protocol_port",
|
||||
"http_cache_port_t",
|
||||
protocol="tcp",
|
||||
port="8081",
|
||||
)
|
||||
== ret
|
||||
)
|
||||
|
||||
# Test failure of adding new policy
|
||||
mock_add = MagicMock(return_value={"retcode": 1})
|
||||
mock_modify = MagicMock(return_value={"retcode": 1})
|
||||
mock_get = MagicMock(return_value=None)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_add_policy": mock_add,
|
||||
"selinux.port_modify_policy": mock_modify,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
comt = "Error adding new policy: {'retcode': 1}"
|
||||
ret.update({"name": name, "comment": comt, "changes": {}, "result": False})
|
||||
assert selinux.port_policy_present(name, "http_cache_port_t") == ret
|
||||
|
||||
|
||||
def test_port_policy_absent():
|
||||
"""
|
||||
Test to delete an SELinux port.
|
||||
"""
|
||||
name = "tcp/8080"
|
||||
protocol = "tcp"
|
||||
port = "8080"
|
||||
ret = {"name": name, "changes": {}, "result": False, "comment": ""}
|
||||
|
||||
# Test policy already removed
|
||||
mock_delete = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(return_value=None)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_delete_policy": mock_delete,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
comt = (
|
||||
f'SELinux policy for "{name}" already absent '
|
||||
+ f'with specified sel_type "http_cache_port_t", protocol "None" '
|
||||
+ f'and port "None".'
|
||||
)
|
||||
ret.update({"comment": comt, "changes": {}, "result": True})
|
||||
assert selinux.port_policy_absent(name, "http_cache_port_t") == ret
|
||||
|
||||
comt = (
|
||||
f'SELinux policy for "name" already absent '
|
||||
+ f'with specified sel_type "http_cache_port_t", protocol "{protocol}" '
|
||||
+ f'and port "{port}".'
|
||||
)
|
||||
ret.update({"comment": comt, "changes": {}, "result": True, "name": "name"})
|
||||
assert (
|
||||
selinux.port_policy_absent("name", "http_cache_port_t", protocol, port)
|
||||
== ret
|
||||
)
|
||||
ret.update({"name": name})
|
||||
|
||||
# Test removing a policy
|
||||
mock_delete = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
side_effect=[
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8080"},
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8080"},
|
||||
None,
|
||||
]
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_delete_policy": mock_delete,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": True}):
|
||||
ret.update({"comment": "", "result": None})
|
||||
assert selinux.port_policy_absent(name, "http_cache_port_t") == ret
|
||||
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
ret.update(
|
||||
{
|
||||
"comment": "",
|
||||
"changes": {
|
||||
"old": {
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
},
|
||||
"new": None,
|
||||
},
|
||||
"result": True,
|
||||
}
|
||||
)
|
||||
assert selinux.port_policy_absent(name, "http_cache_port_t") == ret
|
||||
|
||||
# Test removing a policy using custom name and with protocol and port parameters
|
||||
mock_delete = MagicMock(return_value={"retcode": 0})
|
||||
mock_get = MagicMock(
|
||||
side_effect=[
|
||||
{"sel_type": "http_cache_port_t", "protocol": "tcp", "port": "8081"},
|
||||
None,
|
||||
]
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_delete_policy": mock_delete,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
ret.update(
|
||||
{
|
||||
"name": "required_protocol_port",
|
||||
"comment": "",
|
||||
"changes": {
|
||||
"old": {
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8081",
|
||||
},
|
||||
"new": None,
|
||||
},
|
||||
"result": True,
|
||||
}
|
||||
)
|
||||
assert (
|
||||
selinux.port_policy_absent(
|
||||
"required_protocol_port",
|
||||
"http_cache_port_t",
|
||||
protocol="tcp",
|
||||
port="8081",
|
||||
)
|
||||
== ret
|
||||
)
|
||||
|
||||
# Test failure to delete a policy
|
||||
mock_delete = MagicMock(return_value={"retcode": 2})
|
||||
mock_get = MagicMock(
|
||||
return_value={
|
||||
"sel_type": "http_cache_port_t",
|
||||
"protocol": "tcp",
|
||||
"port": "8080",
|
||||
}
|
||||
)
|
||||
with patch.dict(
|
||||
selinux.__salt__,
|
||||
{
|
||||
"selinux.port_get_policy": mock_get,
|
||||
"selinux.port_delete_policy": mock_delete,
|
||||
},
|
||||
):
|
||||
with patch.dict(selinux.__opts__, {"test": False}):
|
||||
comt = "Error deleting policy: {'retcode': 2}"
|
||||
ret.update({"name": name, "comment": comt, "changes": {}, "result": False})
|
||||
assert selinux.port_policy_absent(name, "http_cache_port_t") == ret
|
||||
|
|
Loading…
Add table
Reference in a new issue