Skip to content

Commit

Permalink
Fix: Step-up checks too narrow (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
pcmxgti authored Dec 19, 2023
1 parent 47cf2be commit 5b46a18
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 17 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Tokendito

<p align="center">
<img src="https://raw.githubusercontent.com/dowjones/tokendito/main/docs/tokendito.png"/>
</p>
Expand Down Expand Up @@ -26,11 +28,19 @@ tokens into your local `~/.aws/credentials` file.

See [Releases](https://github.com/dowjones/tokendito/releases) for a detailed Changelog.

### Tokendito 2.4.0

Version 2.4.0 of Tokendito introduces the following new features:

- Add support for Okta question MFA.
- Many bug fixes and contributions.

### Tokendito 2.3.0

Version 2.3.0 of Tokendito introduces the following new features:

- Basic OIE support while forcing Classic mode.
- Support for saving the Device Token ID for later reuse.
- Misc bug fixes

Note: This feature currently works with locally enabled OIE organizations, but it does not for Organizations with chained Authentication in mixed OIE/Classic environments.
Expand Down
7 changes: 4 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ tokendito --profile engineer
usage: tokendito [-h] [--version] [--configure] [--username OKTA_USERNAME] [--password OKTA_PASSWORD] [--profile USER_CONFIG_PROFILE] [--config-file USER_CONFIG_FILE]
[--loglevel {DEBUG,INFO,WARN,ERROR}] [--log-output-file USER_LOG_OUTPUT_FILE] [--aws-config-file AWS_CONFIG_FILE] [--aws-output AWS_OUTPUT]
[--aws-profile AWS_PROFILE] [--aws-region AWS_REGION] [--aws-role-arn AWS_ROLE_ARN] [--aws-shared-credentials-file AWS_SHARED_CREDENTIALS_FILE]
[--okta-org OKTA_ORG | --okta-tile OKTA_TILE] [--okta-mfa OKTA_MFA] [--okta-mfa-response OKTA_MFA_RESPONSE] [--use-device-token] [--quiet]
[--okta-org OKTA_ORG | --okta-tile OKTA_TILE] [--okta-client-id OKTA_CLIENT_ID] [--okta-mfa OKTA_MFA] [--okta-mfa-response OKTA_MFA_RESPONSE]
[--use-device-token] [--quiet]
Gets an STS token to use with the AWS CLI and SDK.
Expand Down Expand Up @@ -111,9 +112,9 @@ options:
Okta tile URL to use.
--okta-client-id OKTA_CLIENT_ID
For OIE enabled Orgs this sets the Okta client ID to replace the value found by tokendito. It is used in the authorize code flow.
--okta-mfa OKTA_MFA Sets the MFA method
--okta-mfa OKTA_MFA Sets the MFA method. You can also use the TOKENDITO_OKTA_MFA environment variable.
--okta-mfa-response OKTA_MFA_RESPONSE
Sets the MFA response to a challenge
Sets the MFA response to a challenge. You can also use the TOKENDITO_OKTA_MFA_RESPONSE environment variable.
--use-device-token Use device token across sessions
--quiet Suppress output
```
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exclude_lines = [
"break",
"except KeyboardInterrupt:",
"if __name__ == .__main__.:",
"if __package__ is None:",
"if not __package__:",
"logger.debug",
"pragma: no cover",
"print..Invalid input, try again...",
Expand Down
2 changes: 1 addition & 1 deletion tokendito/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# vim: set filetype=python ts=4 sw=4
# -*- coding: utf-8 -*-
"""Tokendito module initialization."""
__version__ = "2.3.3"
__version__ = "2.4.0"
__title__ = "tokendito"
__description__ = "Get AWS STS tokens from Okta SSO"
__long_description_content_type__ = "text/markdown"
Expand Down
2 changes: 1 addition & 1 deletion tokendito/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

def main(args=None): # needed for console script
"""Packge entry point."""
if __package__ is None:
if not __package__:
import os.path

path = os.path.dirname(os.path.dirname(__file__))
Expand Down
2 changes: 1 addition & 1 deletion tokendito/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def authenticate_to_roles(config, urls):
saml_xml = okta.extract_saml_response(saml_response_string)
if not saml_xml:
state_token = okta.extract_state_token(saml_response_string)
if "Extra Verification" in saml_response_string and state_token:
if state_token:
logger.info(f"Step-Up authentication required for {url}.")
if okta.step_up_authenticate(config, state_token):
return authenticate_to_roles(config, urls)
Expand Down
6 changes: 6 additions & 0 deletions tokendito/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def get(self, url, params=None, headers=None, allow_redirects=True):

def post(self, url, data=None, json=None, headers=None, params=None, return_json=False):
"""Perform a POST request."""
response = None
logger.debug(f"POST to {url}")
try:
response = self.session.post(url, data=data, json=json, params=params, headers=headers)
Expand All @@ -95,6 +96,11 @@ def post(self, url, data=None, json=None, headers=None, params=None, return_json
return response
except requests.RequestException as e:
logger.error(f"Error during POST request to {url}. Error: {e}")
if response:
logger.debug(f"Response Headers: {response.headers}")
logger.debug(f"Response Text: {response.text}")
else:
logger.debug("No response received")
sys.exit(1)
except Exception as err:
logger.error(f"The post request to {url} failed with {err}")
Expand Down
14 changes: 11 additions & 3 deletions tokendito/okta.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,11 @@ def get_saml_request(auth_properties):
response = HTTP_client.get(url, headers=headers)

# Extract the required parameters from the SAML request.
post_url = extract_form_post_url(response.text)
base_url = user.get_base_url(post_url)
saml_request = {
"base_url": user.get_base_url(extract_form_post_url(response.text)),
"post_url": extract_form_post_url(response.text),
"base_url": base_url,
"post_url": post_url,
"relay_state": extract_saml_relaystate(response.text),
"request": extract_saml_request(response.text, raw=True),
}
Expand Down Expand Up @@ -263,7 +265,6 @@ def send_saml_response(config, saml_response):

# Get the 'sid' value from the reponse cookies.
sid = response.cookies.get("sid", None)
logger.debug(f"New sid is {sid}")

# If 'sid' is present, mask its value for logging purposes.
if sid:
Expand Down Expand Up @@ -564,6 +565,12 @@ def authorize_request(oauth2_config, oauth2_session_data):
params=payload,
)

idx = HTTP_client.session.cookies.get("idx", None)
if idx:
user.add_sensitive_value_to_be_masked(idx)
else:
logger.debug("We did not find an 'idx' entry in the cookies.")

authorize_code = get_authorize_code(response, session_token)
return authorize_code

Expand Down Expand Up @@ -699,6 +706,7 @@ def idp_authenticate(config):
logger.error("Okta auth failed: unknown type.")
sys.exit(1)

# Possible recursion ahead. The exit condition should be the first if statement.
if local_authentication_enabled(auth_properties):
session_token = local_authenticate(config)
# authentication sends us a token
Expand Down
2 changes: 1 addition & 1 deletion tokendito/tokendito.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

def main(args=None): # needed for console script
"""Packge entry point."""
if __package__ is None:
if not __package__:
import os.path

path = os.path.dirname(os.path.dirname(__file__))
Expand Down
7 changes: 1 addition & 6 deletions tokendito/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,7 @@ def cmd_interface(args):

# get authentication and authorization cookies from okta
okta.access_control(config)
logger.debug(
f"""
about to call discover_tile
we have client cookies: {HTTP_client.session.cookies}
"""
)

if config.okta["tile"]:
tile_label = ""
config.okta["tile"] = (config.okta["tile"], tile_label)
Expand Down

0 comments on commit 5b46a18

Please sign in to comment.