From 7dd7e621b7c091f475d37f5c12c2e4d4e3ce3edf Mon Sep 17 00:00:00 2001
From: pcmxgti <16561338+pcmxgti@users.noreply.github.com>
Date: Mon, 30 Oct 2023 09:48:59 -0400
Subject: [PATCH] Clean up method names for readability
---
tests/unit/test_duo.py | 94 ++++++++++++++++++++---------------------
tests/unit/test_okta.py | 6 +--
tokendito/duo.py | 42 +++++++++---------
tokendito/okta.py | 2 +-
4 files changed, 72 insertions(+), 72 deletions(-)
diff --git a/tests/unit/test_duo.py b/tests/unit/test_duo.py
index e01c18c3..efb95b07 100644
--- a/tests/unit/test_duo.py
+++ b/tests/unit/test_duo.py
@@ -19,10 +19,10 @@ def test_get_passcode(mocker):
assert duo.get_passcode("pytest") is None
-def test_prepare_duo_info():
+def test_prepare_info():
"""Test behaviour empty return duo info."""
from tokendito.config import config
- from tokendito.duo import prepare_duo_info
+ from tokendito.duo import prepare_info
selected_okta_factor = {
"_embedded": {
@@ -55,17 +55,17 @@ def test_prepare_duo_info():
"sid": "",
"version": "3.7",
}
- assert prepare_duo_info(selected_okta_factor) == expected_duo_info
+ assert prepare_info(selected_okta_factor) == expected_duo_info
with pytest.raises(SystemExit) as err:
- prepare_duo_info({"badresponse": "FAIL"})
+ prepare_info({"badresponse": "FAIL"})
assert err.value.code == 1
-def test_get_duo_sid(mocker):
+def test_get_sid(mocker):
"""Check if got sid correct."""
from tokendito.config import config
- from tokendito.duo import get_duo_sid
+ from tokendito.duo import get_sid
test_duo_info = {
"okta_factor": "okta_factor",
@@ -84,16 +84,16 @@ def test_get_duo_sid(mocker):
duo_api_response = Mock()
duo_api_response.url = test_url
- mocker.patch("tokendito.duo.duo_api_post", return_value=duo_api_response)
+ mocker.patch("tokendito.duo.api_post", return_value=duo_api_response)
- duo_sid_info, duo_auth_response = get_duo_sid(test_duo_info)
+ duo_sid_info, duo_auth_response = get_sid(test_duo_info)
assert duo_sid_info["sid"] == "testval"
assert duo_auth_response.url == test_url
- mocker.patch("tokendito.duo.duo_api_post", return_value="FAIL")
+ mocker.patch("tokendito.duo.api_post", return_value="FAIL")
with pytest.raises(SystemExit) as err:
- get_duo_sid(test_duo_info)
+ get_sid(test_duo_info)
assert err.value.code == 2
@@ -119,9 +119,9 @@ def test_get_mfa_response():
assert err.value.code == 1
-def test_duo_api_post(mocker):
+def test_api_post(mocker):
"""Test if duo api post correctly."""
- from tokendito.duo import duo_api_post
+ from tokendito.duo import api_post
mock_post = mocker.patch("requests.Session.post")
mock_resp = mocker.Mock()
@@ -129,13 +129,13 @@ def test_duo_api_post(mocker):
mock_resp.json.return_value = {"status": "pytest"}
mock_post.return_value = mock_resp
- response = duo_api_post("https://pytest/")
+ response = api_post("https://pytest/")
assert response == {"status": "pytest"}
-def test_get_duo_devices(mocker):
+def test_get_devices(mocker):
"""Test that we can get a list of devices."""
- from tokendito.duo import get_duo_devices
+ from tokendito.duo import get_devices
mock_resp = mocker.Mock()
mock_resp.status_code = 200
@@ -143,7 +143,7 @@ def test_get_duo_devices(mocker):
# Test generic failure or empty response
with pytest.raises(SystemExit) as err:
- get_duo_devices(mock_resp)
+ get_devices(mock_resp)
assert err.value.code == 2
# Test no devices in list
@@ -152,7 +152,7 @@ def test_get_duo_devices(mocker):
"""
- assert get_duo_devices(mock_resp) == []
+ assert get_devices(mock_resp) == []
# Test devices in list
mock_resp.content = """
@@ -163,46 +163,46 @@ def test_get_duo_devices(mocker):
"""
- assert get_duo_devices(mock_resp) == [
+ assert get_devices(mock_resp) == [
{"device": "pytest_device - pytest_device_name", "factor": "factor_type"}
]
-def test_parse_duo_mfa_challenge():
+def test_parse_mfa_challenge():
"""Test parsing the response to the challenge."""
- from tokendito.duo import parse_duo_mfa_challenge
+ from tokendito.duo import parse_mfa_challenge
mfa_challenge = Mock()
# Test successful challenge
mfa_challenge.json = Mock(return_value={"stat": "OK", "response": {"txid": "pytest"}})
- assert parse_duo_mfa_challenge(mfa_challenge) == "pytest"
+ assert parse_mfa_challenge(mfa_challenge) == "pytest"
# Test error
mfa_challenge.json = Mock(return_value={"stat": "OK", "response": "error"})
with pytest.raises(SystemExit) as err:
- parse_duo_mfa_challenge(mfa_challenge)
+ parse_mfa_challenge(mfa_challenge)
assert err.value.code == 1
# Test no response in returned content
mfa_challenge.json = Mock(return_value={"stat": "OK", "badresponse": "error"})
with pytest.raises(SystemExit) as err:
- parse_duo_mfa_challenge(mfa_challenge)
+ parse_mfa_challenge(mfa_challenge)
assert err.value.code == 1
# Test API failure
mfa_challenge.json = Mock(return_value={"stat": "fail", "response": {"txid": "error"}})
with pytest.raises(SystemExit) as err:
- parse_duo_mfa_challenge(mfa_challenge)
+ parse_mfa_challenge(mfa_challenge)
assert err.value.code == 1
-def test_duo_mfa_challenge(mocker):
+def test_mfa_challenge(mocker):
"""TODO: Test MFA challenge."""
- from tokendito.duo import duo_mfa_challenge
+ from tokendito.duo import mfa_challenge
with pytest.raises(SystemExit) as err:
- duo_mfa_challenge(None, None, None)
+ mfa_challenge(None, None, None)
assert err.value.code == 2
duo_info = {
@@ -223,9 +223,9 @@ def test_duo_mfa_challenge(mocker):
duo_api_response = mocker.Mock()
duo_api_response.json.return_value = {"stat": "OK", "response": {"txid": "pytest_txid"}}
- mocker.patch("tokendito.duo.duo_api_post", return_value=duo_api_response)
+ mocker.patch("tokendito.duo.api_post", return_value=duo_api_response)
- txid = duo_mfa_challenge(duo_info, mfa_option, passcode)
+ txid = mfa_challenge(duo_info, mfa_option, passcode)
assert txid == "pytest_txid"
@@ -249,12 +249,12 @@ def test_parse_challenge():
(("failure", "pytest"), None, SystemExit),
],
)
-def test_duo_mfa_verify(mocker, return_value, side_effect, expected):
+def test_mfa_verify(mocker, return_value, side_effect, expected):
"""Test MFA challenge completion.
side_effect is utilized to return different values on different iterations.
"""
- from tokendito.duo import duo_mfa_verify
+ from tokendito.duo import mfa_verify
mocker.patch.object(HTTP_client, "post", return_value=None)
mocker.patch("time.sleep", return_value=None)
@@ -269,16 +269,16 @@ def test_duo_mfa_verify(mocker, return_value, side_effect, expected):
if expected == SystemExit:
# Test failure as exit condition
with pytest.raises(expected) as err:
- duo_mfa_verify(duo_info, txid)
+ mfa_verify(duo_info, txid)
assert err.value.code == 2
else:
# Test success, failure, and iterated calls
- assert duo_mfa_verify(duo_info, txid) == expected
+ assert mfa_verify(duo_info, txid) == expected
-def test_duo_factor_callback(mocker):
+def test_factor_callback(mocker):
"""Test submitting factor to callback API."""
- from tokendito.duo import duo_factor_callback
+ from tokendito.duo import factor_callback
duo_info = {"host": "pytest_host", "sid": "pytest_sid", "tile_sig": "pytest_tile_sig"}
verify_mfa = {"result_url": "/pytest_result_url"}
@@ -288,25 +288,25 @@ def test_duo_factor_callback(mocker):
"stat": "OK",
"response": {"txid": "pytest_txid", "cookie": "pytest_cookie"},
}
- mocker.patch("tokendito.duo.duo_api_post", return_value=duo_api_response)
+ mocker.patch("tokendito.duo.api_post", return_value=duo_api_response)
# Test successful retrieval of the cookie
- sig_response = duo_factor_callback(duo_info, verify_mfa)
+ sig_response = factor_callback(duo_info, verify_mfa)
assert sig_response == "pytest_cookie:pytest_tile_sig"
# Test failure to retrieve the cookie
duo_api_response.json.return_value = {"stat": "FAIL", "response": "pytest_error"}
with pytest.raises(SystemExit) as err:
- duo_factor_callback(duo_info, verify_mfa)
+ factor_callback(duo_info, verify_mfa)
assert err.value.code == 2
-def test_authenticate_duo(mocker):
+def test_authenticate(mocker):
"""Test end to end authentication."""
- from tokendito.duo import authenticate_duo
+ from tokendito.duo import authenticate
mocker.patch(
- "tokendito.duo.get_duo_sid",
+ "tokendito.duo.get_sid",
return_value=(
{
"sid": "pytest",
@@ -320,13 +320,13 @@ def test_authenticate_duo(mocker):
)
# We mock a lot of functions here, but we're really just testing that the data can flow,
# and that it can be parsed correctly to be sent to the API endpoint.
- mocker.patch("tokendito.duo.get_duo_devices", return_value=[{"device": "pytest - device"}])
+ mocker.patch("tokendito.duo.get_devices", return_value=[{"device": "pytest - device"}])
mocker.patch("tokendito.user.select_preferred_mfa_index", return_value=0)
mocker.patch("tokendito.user.input", return_value="0123456")
- mocker.patch("tokendito.duo.duo_mfa_challenge", return_value="txid_pytest")
- mocker.patch("tokendito.duo.duo_mfa_verify", return_value={"result_url": "/pytest_result_url"})
- mocker.patch("tokendito.duo.duo_api_post", return_value=None)
- mocker.patch("tokendito.duo.duo_factor_callback", return_value="pytest_cookie:pytest_tile_sig")
+ mocker.patch("tokendito.duo.mfa_challenge", return_value="txid_pytest")
+ mocker.patch("tokendito.duo.mfa_verify", return_value={"result_url": "/pytest_result_url"})
+ mocker.patch("tokendito.duo.api_post", return_value=None)
+ mocker.patch("tokendito.duo.factor_callback", return_value="pytest_cookie:pytest_tile_sig")
selected_okta_factor = {
"_embedded": {
"factor": {
@@ -346,7 +346,7 @@ def test_authenticate_duo(mocker):
"stateToken": 12345,
}
- res = authenticate_duo(selected_okta_factor)
+ res = authenticate(selected_okta_factor)
assert {
"id": "pytest",
"sig_response": "pytest_cookie:pytest_tile_sig",
diff --git a/tests/unit/test_okta.py b/tests/unit/test_okta.py
index 1d322b7d..7162b1d5 100644
--- a/tests/unit/test_okta.py
+++ b/tests/unit/test_okta.py
@@ -89,7 +89,7 @@ def test_mfa_provider_type(
mock_response = {"sessionToken": session_token}
mocker.patch.object(HTTP_client, "post", return_value=mock_response)
- mocker.patch("tokendito.duo.duo_api_post", return_value=None)
+ mocker.patch("tokendito.duo.api_post", return_value=None)
payload = {"x": "y", "t": "z"}
selected_mfa_option = 1
@@ -97,7 +97,7 @@ def test_mfa_provider_type(
primary_auth = 1
pytest_config = Config()
- mocker.patch("tokendito.duo.authenticate_duo", return_value=payload)
+ mocker.patch("tokendito.duo.authenticate", return_value=payload)
mocker.patch("tokendito.okta.push_approval", return_value={"sessionToken": session_token})
mocker.patch("tokendito.okta.totp_approval", return_value={"sessionToken": session_token})
@@ -135,7 +135,7 @@ def test_bad_mfa_provider_type(mocker, sample_headers):
mock_response = Mock()
mock_response.json.return_value = mfa_verify
- mocker.patch("tokendito.duo.authenticate_duo", return_value=payload)
+ mocker.patch("tokendito.duo.authenticate", return_value=payload)
mocker.patch.object(HTTP_client, "post", return_value=mock_response)
mocker.patch("tokendito.okta.totp_approval", return_value=mfa_verify)
diff --git a/tokendito/duo.py b/tokendito/duo.py
index ba3b25c2..3853dcbd 100644
--- a/tokendito/duo.py
+++ b/tokendito/duo.py
@@ -17,7 +17,7 @@
logger = logging.getLogger(__name__)
-def prepare_duo_info(selected_okta_factor):
+def prepare_info(selected_okta_factor):
"""Aggregate most of the parameters needed throughout the Duo authentication process.
:param selected_okta_factor: dict response describing Duo factor in Okta.
@@ -45,7 +45,7 @@ def prepare_duo_info(selected_okta_factor):
return duo_info
-def duo_api_post(url, params=None, headers=None, payload=None):
+def api_post(url, params=None, headers=None, payload=None):
"""Error handling and response parsing wrapper for Duo POSTs.
:param url: The URL being connected to.
@@ -58,7 +58,7 @@ def duo_api_post(url, params=None, headers=None, payload=None):
return response
-def get_duo_sid(duo_info):
+def get_sid(duo_info):
"""Perform the initial Duo authentication request to obtain the SID.
The SID is referenced throughout the authentication process for Duo.
@@ -71,7 +71,7 @@ def get_duo_sid(duo_info):
url = f"https://{duo_info['host']}/frame/web/v1/auth"
logger.debug(f"Calling Duo {urlparse(url).path} with params {params.keys()}")
- duo_auth_response = duo_api_post(url, params=params)
+ duo_auth_response = api_post(url, params=params)
try:
duo_auth_redirect = urlparse(f"{unquote(duo_auth_response.url)}").query
@@ -83,7 +83,7 @@ def get_duo_sid(duo_info):
return (duo_info, duo_auth_response)
-def get_duo_devices(duo_auth):
+def get_devices(duo_auth):
"""Parse Duo auth response to extract user's MFA options.
The /frame/web/v1/auth API returns an html page that lists
@@ -117,7 +117,7 @@ def get_duo_devices(duo_auth):
return factor_options
-def parse_duo_mfa_challenge(mfa_challenge):
+def parse_mfa_challenge(mfa_challenge):
"""Gracefully parse Duo MFA challenge response.
:param mfa_challenge: Duo API response for MFA challenge.
@@ -141,7 +141,7 @@ def parse_duo_mfa_challenge(mfa_challenge):
return txid
-def duo_mfa_challenge(duo_info, mfa_option, passcode):
+def mfa_challenge(duo_info, mfa_option, passcode):
"""Poke Duo to challenge the selected factor.
After the user has selected their device and factor of choice,
@@ -171,8 +171,8 @@ def duo_mfa_challenge(duo_info, mfa_option, passcode):
if passcode:
mfa_data["passcode"] = passcode
- mfa_challenge = duo_api_post(url, payload=mfa_data)
- txid = parse_duo_mfa_challenge(mfa_challenge)
+ mfa_challenge = api_post(url, payload=mfa_data)
+ txid = parse_mfa_challenge(mfa_challenge)
logger.debug(f"Sent MFA Challenge and obtained Duo transaction ID {txid}")
return txid
@@ -219,7 +219,7 @@ def parse_challenge(verify_mfa, challenge_result):
return (challenge_result, challenge_reason)
-def duo_mfa_verify(duo_info, txid):
+def mfa_verify(duo_info, txid):
"""Verify MFA challenge completion.
After the user has received the MFA challenge, query the Duo API
@@ -235,7 +235,7 @@ def duo_mfa_verify(duo_info, txid):
while True:
logger.debug("Waiting for MFA challenge response")
- mfa_result = duo_api_post(url, payload=challenged_mfa)
+ mfa_result = api_post(url, payload=challenged_mfa)
verify_mfa = get_mfa_response(mfa_result)
(challenge_result, challenge_reason) = parse_challenge(verify_mfa, challenge_result)
@@ -252,7 +252,7 @@ def duo_mfa_verify(duo_info, txid):
return verify_mfa
-def duo_factor_callback(duo_info, verify_mfa):
+def factor_callback(duo_info, verify_mfa):
"""Inform factor callback api of successful challenge.
This request seems to inform this factor's callback url
@@ -263,7 +263,7 @@ def duo_factor_callback(duo_info, verify_mfa):
:return sig_response: required to sign final Duo callback request.
"""
factor_callback_url = f"https://{duo_info['host']}{verify_mfa['result_url']}"
- factor_callback = duo_api_post(factor_callback_url, payload={"sid": duo_info["sid"]})
+ factor_callback = api_post(factor_callback_url, payload={"sid": duo_info["sid"]})
try:
sig_response = f"{factor_callback.json()['response']['cookie']}:{duo_info['tile_sig']}"
@@ -295,7 +295,7 @@ def get_passcode(mfa_option):
return passcode
-def authenticate_duo(selected_okta_factor):
+def authenticate(selected_okta_factor):
"""Accomplish MFA via Duo.
This is the main function that coordinates the Duo
@@ -305,10 +305,10 @@ def authenticate_duo(selected_okta_factor):
:param selected_okta_factor: Duo factor information retrieved from Okta.
:return payload: required payload for Okta callback
"""
- duo_info = prepare_duo_info(selected_okta_factor)
+ duo_info = prepare_info(selected_okta_factor)
# Collect devices, factors, auth params for Duo
- (duo_info, duo_auth_response) = get_duo_sid(duo_info)
- factor_options = get_duo_devices(duo_auth_response)
+ (duo_info, duo_auth_response) = get_sid(duo_info)
+ factor_options = get_devices(duo_auth_response)
mfa_index = user.select_preferred_mfa_index(
factor_options, factor_key="factor", subfactor_key="device"
)
@@ -317,11 +317,11 @@ def authenticate_duo(selected_okta_factor):
logger.debug(f"Selected MFA is [{mfa_option}]")
passcode = get_passcode(mfa_option)
- txid = duo_mfa_challenge(duo_info, mfa_option, passcode)
- verify_mfa = duo_mfa_verify(duo_info, txid)
+ txid = mfa_challenge(duo_info, mfa_option, passcode)
+ verify_mfa = mfa_verify(duo_info, txid)
# Make factor callback to Duo
- sig_response = duo_factor_callback(duo_info, verify_mfa)
+ sig_response = factor_callback(duo_info, verify_mfa)
# Prepare for Okta callback
payload = {
@@ -331,5 +331,5 @@ def authenticate_duo(selected_okta_factor):
}
# Send Okta callback and return payload
- duo_api_post(duo_info["okta_callback_url"], payload=payload)
+ api_post(duo_info["okta_callback_url"], payload=payload)
return payload
diff --git a/tokendito/okta.py b/tokendito/okta.py
index 9c33b4e4..1fa249bd 100644
--- a/tokendito/okta.py
+++ b/tokendito/okta.py
@@ -464,7 +464,7 @@ def mfa_provider_type(
factor_type = selected_factor.get("_embedded", {}).get("factor", {}).get("factorType", None)
if mfa_provider == "DUO":
- mfa_verify = duo.authenticate_duo(selected_factor)
+ mfa_verify = duo.authenticate(selected_factor)
headers = {"content-type": "application/json", "accept": "application/json"}
mfa_verify = HTTP_client.post(
mfa_challenge_url, json=payload, headers=headers, return_json=True