Skip to content

Commit

Permalink
Update secret filtering logic, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davidesner committed May 28, 2024
1 parent 8bfc3fd commit 91b9d23
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 36 deletions.
58 changes: 28 additions & 30 deletions python-sync-actions/src/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,19 @@ def init_component(self):
auth_method=auth_method
)

def _get_values_to_hide(self, values: dict):
def _get_values_to_hide(self) -> list[str]:
"""
Get values to hide
Args:
values: values to hide
"""
return [value for key, value in values.items() if key.startswith('#') or key.startswith('__')]
user_params = self._configuration.user_parameters
secrets = [value for key, value in user_params.items() if key.startswith('#') or key.startswith('__')]

# get secrets from the auth method
if self._client._auth_method: # noqa
auth_secrets = self._client._auth_method.get_secrets() # noqa
secrets.extend(auth_secrets)
return secrets

def _replace_words(self, obj, words, replacement="--HIDDEN--"):
# Helper function to perform replacement in strings
Expand Down Expand Up @@ -337,11 +343,7 @@ def recursive_call(parent_result, config_index=0):
else:
raise UserException(e) from e

secrets_to_hide = self._get_values_to_hide(self._configuration.user_parameters)
filtered_response = self._deep_copy_and_replace_words(self._final_response, secrets_to_hide)
filtered_log = self._deep_copy_and_replace_words(self.log.getvalue(), secrets_to_hide)

return final_results, filtered_response, filtered_log, error_message
return final_results, self._final_response, self.log.getvalue(), error_message

@sync_action('load_from_curl')
def load_from_curl(self) -> dict:
Expand Down Expand Up @@ -399,41 +401,37 @@ def perform_function_sync(self) -> dict:
def test_request(self):
results, response, log, error_message = self.make_call()

# TODO: UI to parse the response status code

body = None
if self._final_response.request.body:
body = self._final_response.request.body.decode('utf-8')
if response.request.body:
body = response.request.body.decode('utf-8')

secrets_to_hide = self._get_values_to_hide()
filtered_response = self._deep_copy_and_replace_words(self._final_response, secrets_to_hide)
filtered_log = self._deep_copy_and_replace_words(self.log.getvalue(), secrets_to_hide)
filtered_body = self._deep_copy_and_replace_words(body, secrets_to_hide)

# get response data:
try:
response_data = self._final_response.json()
response_data = filtered_response.json()
except JSONDecodeError:
response_data = self._final_response.text
response_data = filtered_response.text

result = {
"response": {
"status_code": self._final_response.status_code,
"reason": self._final_response.reason,
"status_code": filtered_response.status_code,
"reason": filtered_response.reason,
"data": response_data,
"headers": dict(self._final_response.headers)
"headers": dict(filtered_response.headers)
},
"request": {
"url": self._final_response.request.url,
"method": self._final_response.request.method,
"data": body,
"headers": dict(self._final_response.request.headers)
"url": response.request.url,
"method": response.request.method,
"data": filtered_body,
"headers": dict(filtered_response.request.headers)
},
"records": results,
"debug_log": log
"debug_log": filtered_log
}
# # filter secrets
# # TODO: temp override for demo, do all secrets when ready
# # TODO: handle situation when secret is number
# # -> replacing "some": 123 with "some": HIDDEN would lead to invalid json
# secret = self.configuration.parameters.get('config', {}).get('#__AUTH_TOKEN', '')
# result_str = json.dumps(result)
# result_str = result_str.replace(secret, 'HIDDEN')
# return json.loads(result_str)
return result


Expand Down
37 changes: 37 additions & 0 deletions python-sync-actions/src/http_generic/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from urllib.parse import urlencode

import requests
from requests import auth
from requests.auth import AuthBase, HTTPBasicAuth

from configuration import ContentType, ConfigHelpers
Expand All @@ -30,6 +31,15 @@ def login(self):
"""
pass

@abstractmethod
def get_secrets(self) -> list[str]:
"""
Helper method to apply loging filters
Returns:
"""
pass


class AuthMethodBuilder:

Expand Down Expand Up @@ -104,9 +114,15 @@ def __eq__(self, other):
self.password == getattr(other, 'password', None)
])

def get_secrets(self):
return auth._basic_auth_str(self.username, self.password)


class BearerToken(AuthMethodBase, AuthBase):

def get_secrets(self) -> list[str]:
return [self.token]

def __init__(self, __token):
self.token = __token

Expand All @@ -127,6 +143,9 @@ def __call__(self, r):


class ApiKey(AuthMethodBase, AuthBase):
def get_secrets(self) -> list[str]:
return [self.token]

def __init__(self, key: str, token: str, position: str):
self.token = token
self.key = key
Expand Down Expand Up @@ -155,6 +174,9 @@ def __call__(self, r):


class Query(AuthMethodBase, AuthBase):
def get_secrets(self) -> list[str]:
return [value for value in self.params.values()]

def __init__(self, params: Dict):
self.params = params

Expand All @@ -167,6 +189,7 @@ def __call__(self, r):


class Login(AuthMethodBase, AuthBase):

def __init__(self, login_endpoint: str, method: str = 'GET',
login_query_parameters: dict = None,
login_query_body=None,
Expand Down Expand Up @@ -253,6 +276,16 @@ def login(self) -> Union[AuthBase, Callable]:
True)
return self

def get_secrets(self) -> list[str]:
secrets = []
for key, value in self.api_request_query_parameters.items():
secrets.append(value)

for key, value in self.api_request_headers.items():
secrets.append(value)

return secrets

def __call__(self, r):

r.url = f"{r.url}"
Expand All @@ -263,6 +296,7 @@ def __call__(self, r):


class OAuth20ClientCredentials(AuthMethodBase, AuthBase):

def __init__(self, login_endpoint: str,
client_secret: str,
client_id: str,
Expand Down Expand Up @@ -304,6 +338,9 @@ def login(self) -> Union[AuthBase, Callable]:

return self

def get_secrets(self) -> list[str]:
return [self.auth_header['Authorization']]

def __call__(self, r):
r.headers.update(self.auth_header)
return r
22 changes: 16 additions & 6 deletions python-sync-actions/tests/test_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,27 @@ def _get_test_component(self, test_name):

def test_003_oauth_cc(self):
component = self._get_test_component(self._testMethodName)
output = component.test_request()
results, response, log, error_message = component.make_call()
expected_data = [{'id': '321', 'status': 'get'}, {'id': 'girlfriend', 'status': 'imaginary'}]
self.assertEqual(output['response']['data'], expected_data)
self.assertTrue(output['request']['headers']['Authorization'].startswith('Bearer '))
self.assertEqual(results, expected_data)
self.assertTrue(response.request.headers['Authorization'].startswith('Bearer '))

def test_003_oauth_cc_filtered(self):
component = self._get_test_component('test_003_oauth_cc')
results = component.test_request()
self.assertEqual(results['request']['headers']['Authorization'], '--HIDDEN--')

def test_004_oauth_cc_post(self):
component = self._get_test_component(self._testMethodName)
output = component.test_request()
results, response, log, error_message = component.make_call()
expected_data = [{'id': '321', 'status': 'get'}, {'id': 'girlfriend', 'status': 'imaginary'}]
self.assertEqual(output['response']['data'], expected_data)
self.assertTrue(output['request']['headers']['Authorization'].startswith('Bearer '))
self.assertEqual(results, expected_data)
self.assertTrue(response.request.headers['Authorization'].startswith('Bearer '))

def test_004_oauth_cc_post_filtered(self):
component = self._get_test_component('test_004_oauth_cc_post')
results = component.test_request()
self.assertEqual(results['request']['headers']['Authorization'], '--HIDDEN--')

def test_005_post(self):
component = self._get_test_component(self._testMethodName)
Expand Down

0 comments on commit 91b9d23

Please sign in to comment.