diff --git a/CHANGELOG b/CHANGELOG index 42f8394..66868ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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. diff --git a/MANIFEST b/MANIFEST index 00c1a65..807046f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -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 diff --git a/Pipfile b/Pipfile index 5061c9c..4e96e60 100644 --- a/Pipfile +++ b/Pipfile @@ -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" diff --git a/lib/plugin.py b/lib/plugin.py index afb736a..188cda1 100644 --- a/lib/plugin.py +++ b/lib/plugin.py @@ -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 @@ -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])) diff --git a/lib/tests/unit/test_plugin.py b/lib/tests/unit/test_plugin.py index d4b928f..e94f1a7 100644 --- a/lib/tests/unit/test_plugin.py +++ b/lib/tests/unit/test_plugin.py @@ -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", } @@ -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) @@ -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} @@ -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"}, ) )