Skip to content

Commit

Permalink
Merge pull request #4 from OneIdentity/use_readable_deny_reason
Browse files Browse the repository at this point in the history
RADIUS: use human-readable deny reason in plugin response
  • Loading branch information
ddomeb authored Aug 31, 2020
2 parents 43ab676 + c8de067 commit fdabc46
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
3.0.0 2020-08-19

Use human-readable deny reason in plugin response.

2.0.5 2019-04-19

Initial release on GitHub.
Expand Down
4 changes: 2 additions & 2 deletions MANIFEST
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: SPS_RADIUS
description: RADIUS (RSA) Multi-Factor Authentication plugin
version: 2.0.5
version: 3.0.0
type: aa
api: 1.1
api: 1.6
entry_point: main.py
author_name: One Identity PAM Integration Team
author_email: QDL.QBU-OI.RD.Safeguard.Integration@oneidentity.com
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pyrad = "*"

[dev-packages]
pyrad = "*"
oneidentity-safeguard-sessions-plugin-sdk = "~=1.1.0"
oneidentity-safeguard-sessions-plugin-sdk = "~=1.6.0"

[requires]
python_version = "3.6"
14 changes: 8 additions & 6 deletions lib/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
from re import sub
from socket import error as socket_error

from safeguard.sessions.plugin import AAPlugin, AAResponse
from safeguard.sessions.plugin import AAPlugin
from safeguard.sessions.plugin.plugin_response import DenyReasons, AAResponse
from pyrad.packet import AccessReject, AccessAccept, AccessChallenge

from .radius import RadiusClient
Expand Down Expand Up @@ -60,22 +61,23 @@ def do_authenticate(self):
radrep = radcli.authenticate(username=radius_username, password=self.mfa_password, state=prev_state)
except TimeoutError:
self.logger.error("Network timeout while talking to RADIUS server.")
return AAResponse.deny()
return AAResponse.deny(deny_reason=DenyReasons().backend_service_error)
except socket_error as ex:
self.logger.error("Network error while talking to RADIUS server: %s", ex)
return AAResponse.deny()
return AAResponse.deny(deny_reason=DenyReasons().communication_error)
except Exception as ex:
self.logger.error("An exception of type %s occured. Arguments:\n%s", type(ex).__name__, ex.args)
self.logger.error(
"An exception of type %s occured. Arguments:\n%s", type(ex).__name__, ex.args,
)
self.logger.debug("Exception details follow.", exc_info=ex)
return AAResponse.deny()

if radrep.code == AccessAccept:
self.logger.info("RADIUS authentication was successful!")
return AAResponse.accept()

elif radrep.code == AccessReject:
self.logger.info("RADIUS authentication was rejected!")
return AAResponse.deny()
return AAResponse.deny(deny_reason=DenyReasons().authentication_failure)
elif radrep.code == AccessChallenge:
self.logger.info("RADIUS challenge received")
challenge = sub("\x00", "", "".join(radrep["Reply-Message"][0]))
Expand Down
33 changes: 16 additions & 17 deletions lib/tests/unit/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,23 @@ def fake_plugin_context(monkeypatch):
monkeypatch.setitem(os.environ, "EPHEMERAL_PLUGIN_STATE_DIRECTORY", ephemeral_dir)
yield


def provide_get_radius_username_cases():
yield {
"params": {"gateway_user": "gwuser", "key_value_pairs": {}, "target_username": "tguser"},
"params": {"gateway_user": "gwuser", "key_value_pairs": {}, "server_username": "srvuser"},
"expected": "gwuser",
}
yield {"params": {"gateway_user": None, "key_value_pairs": {}, "target_username": "tguser"}, "expected": "tguser"}
yield {"params": {"gateway_user": None, "key_value_pairs": {}, "target_username": None}, "expected": None}
yield {"params": {"gateway_user": None, "key_value_pairs": {}, "server_username": "srvuser"}, "expected": "srvuser"}
yield {"params": {"gateway_user": None, "key_value_pairs": {}, "server_username": None}, "expected": None}
yield {
"params": {
"gateway_user": "gwuser",
"key_value_pairs": {"radius_username": "radiususer", "ru": "ruuser"},
"target_username": "tguser",
"server_username": "srvuser",
},
"expected": "radiususer",
}
yield {
"params": {"gateway_user": "gwuser", "key_value_pairs": {"ru": "ruuser"}, "target_username": "tguser"},
"params": {"gateway_user": "gwuser", "key_value_pairs": {"ru": "ruuser"}, "server_username": "srvuser"},
"expected": "ruuser",
}

Expand All @@ -101,8 +100,7 @@ def test_get_radius_username(tc):
def check_tc(params, expected):
config = ""
plugin = Plugin(config)
plugin.authenticate(**(enrich_params_with_mandatory_keys(params)))
print(plugin.cookie)
plugin.authenticate(**enrich_params_with_mandatory_keys(params))
assert plugin.cookie.get("mfa_identity") == expected

check_tc(**tc)
Expand All @@ -122,24 +120,25 @@ def check_tc(params, expected):

check_tc(**tc)


def enrich_params_with_mandatory_keys(params):
connection_parameters = {
"cookie": {},
"session_cookie": {},
"session_id": "",
"protocol": "",
"protocol": "SSH",
"connection_name": "",
"client_ip": "",
"client_port": "",
"gateway_user": "",
"target_username": "",
"key_value_pairs": {},
"cookie": {},
"session_cookie": {},
"client_hostname": "",
"gateway_user": None,
"gateway_domain": None,
"server_username": None,
"server_domain": None,
"key_value_pairs": {}
}
connection_parameters.update(params)
return connection_parameters


def provide_get_radius_password_cases():
yield {"params": {"key_value_pairs": {}}, "expected": None}
yield {"params": {"key_value_pairs": {}}, "expected": None}
Expand Down Expand Up @@ -193,7 +192,7 @@ def test_authenticate_with_only_target_user():
dict(
cookie={},
client_ip="1.2.3.4",
target_username="the_username",
server_username="the_username",
key_value_pairs={"radius_password": "the_password"},
)
)
Expand Down

0 comments on commit fdabc46

Please sign in to comment.