Skip to content

Commit

Permalink
Merge pull request #101 from kuefmz/config_via_auth
Browse files Browse the repository at this point in the history
Logic to parse config from proxy auth
  • Loading branch information
JJ-Author authored Oct 21, 2024
2 parents 3ce4e0c + bb85c0f commit 60bfb9c
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 44 deletions.
82 changes: 65 additions & 17 deletions ontologytimemachine/custom_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def __init__(self, *args, **kwargs):
logger.info(f"Init - Object ID: {id(self)}")
super().__init__(*args, **kwargs)
self.config = config
self.current_config = None
logger.info(self.config)

def before_upstream_connection(self, request: HttpParser) -> HttpParser | None:
# self.client.config = None
Expand All @@ -47,49 +47,97 @@ def before_upstream_connection(self, request: HttpParser) -> HttpParser | None:
)
wrapped_request = HttpRequestWrapper(request)

# if self.config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.REQUIRED:
# self.client.config = evaluate_configuration(wrapped_request, self.config)
if (
self.config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.REQUIRED
or self.config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.OPTIONAL
):
config_from_auth = evaluate_configuration(wrapped_request, self.config)
if (
not config_from_auth
and self.config.clientConfigViaProxyAuth
== ClientConfigViaProxyAuth.REQUIRED
):
logger.info(
"Client configuration via proxy auth is required btu configuration is not provided, return 500."
)
self.queue_response(mock_response_500)
return None
if (
not config_from_auth
and self.config.clientConfigViaProxyAuth
== ClientConfigViaProxyAuth.OPTIONAL
):
logger.info("Auth configuration is optional, not procided.")
if config_from_auth and not hasattr(self.client, "config"):
self.client.config = config_from_auth
logger.info(f"New config: {config_from_auth}")
if self.config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.IGNORE:
logger.info("Ignore auth even if provided")

# Check if any config was provided via the authentication parameters
# If so, use that config
if hasattr(self.client, "config"):
logger.info("Using the configuration from the Auth")
config = self.client.config
else:
logger.info("Using the proxy configuration")
config = self.config

if wrapped_request.is_connect_request():
logger.info(
f"Handling CONNECT request: configured HTTPS interception mode: {self.config.httpsInterception}"
f"Handling CONNECT request: configured HTTPS interception mode: {config.httpsInterception}"
)

# Check whether to allow CONNECT requests since they can impose a security risk
if not do_block_CONNECT_request(self.config):
if not do_block_CONNECT_request(config):
logger.info("Allowing the CONNECT request")
return request
else:
logger.info("CONNECT request was blocked due to the configuration")
return None

# # If only ontology mode, return None in all other cases
logger.info(f"Config: {self.config}")
response = get_response_from_request(wrapped_request, self.config)
logger.info(f"Config: {config}")
response = get_response_from_request(wrapped_request, config)
if response:
self.queue_response(response)
self.current_config = None
return None

return request

def do_intercept(self, _request: HttpParser) -> bool:
wrapped_request = HttpRequestWrapper(_request)
if self.config.httpsInterception == HttpsInterception.ALL:

# Check if any config was provided via the authentication parameters
# If so, use that config
if hasattr(self.client, "config"):
logger.info("Using the configuration from the Auth")
config = self.client.config
else:
logger.info("Using the proxy configuration")
config = self.config

if config.httpsInterception == HttpsInterception.ALL:
logger.info("Intercepting all HTTPS requests")
return True
elif self.config.httpsInterception == HttpsInterception.NONE:
elif config.httpsInterception == HttpsInterception.NONE:
logger.info("Intercepting no HTTPS requests")
return False
elif self.config.httpsInterception == HttpsInterception.BLOCK:
logger.error("Reached code block for interception decision in block mode which should have been blocked before")
#this should actually be not triggered as the CONNECT request should have been blocked before
elif config.httpsInterception == HttpsInterception.BLOCK:
logger.error(
"Reached code block for interception decision in block mode which should have been blocked before"
)
# this should actually be not triggered as the CONNECT request should have been blocked before
return False
elif self.config.httpsInterception == HttpsInterception.ARCHIVO:
elif config.httpsInterception == HttpsInterception.ARCHIVO:
if is_archivo_ontology_request(wrapped_request):
logger.info("Intercepting HTTPS request since it is an Archivo ontology request")
logger.info(
"Intercepting HTTPS request since it is an Archivo ontology request"
)
return True
logger.info("No Interception of HTTPS request since it is NOT an Archivo ontology request")
logger.info(
"No Interception of HTTPS request since it is NOT an Archivo ontology request"
)
return False
else:
logger.info(
Expand Down Expand Up @@ -131,7 +179,7 @@ def queue_response(self, response):
sys.argv = [sys.argv[0]]

# check it https interception is enabled
if config.httpsInterception != "none":
if config.httpsInterception != HttpsInterception.NONE:
sys.argv += [
"--ca-key-file",
"ca-key.pem",
Expand Down
13 changes: 7 additions & 6 deletions ontologytimemachine/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ class Config:
ontoFormatConf: OntoFormatConfig = field(default_factory=OntoFormatConfig)
ontoVersion: OntoVersion = OntoVersion.ORIGINAL_FAILOVER_LIVE_LATEST
restrictedAccess: bool = False
clientConfigViaProxyAuth: ClientConfigViaProxyAuth = (
ClientConfigViaProxyAuth.REQUIRED
)
clientConfigViaProxyAuth: ClientConfigViaProxyAuth = ClientConfigViaProxyAuth.IGNORE
httpsInterception: HttpsInterception = HttpsInterception.ALL
disableRemovingRedirects: bool = False
timestamp: str = ""
Expand Down Expand Up @@ -156,7 +154,7 @@ def parse_arguments(config_str: str = "") -> Config:
type=lambda s: enum_parser(ClientConfigViaProxyAuth, s),
default=default_cfg.clientConfigViaProxyAuth,
choices=list(ClientConfigViaProxyAuth),
help="Define the config.",
help="Define the configuration of the proxy via the proxy auth.",
)

# Log level
Expand All @@ -168,7 +166,10 @@ def parse_arguments(config_str: str = "") -> Config:
help="Level of the logging: debug, info, warning, error.",
)

args = parser.parse_args(config_str)
if config_str:
args = parser.parse_args(config_str)
else:
args = parser.parse_args()

# Check the value of --ontoVersion and prompt for additional arguments if needed
if args.ontoVersion == "timestampArchived":
Expand All @@ -190,7 +191,7 @@ def parse_arguments(config_str: str = "") -> Config:
# manifest = None

# print the default configuration with all nested members
print(default_cfg) # TODO remove
# print(default_cfg) # TODO remove

# Initialize the Config class with parsed arguments
config = Config(
Expand Down
27 changes: 19 additions & 8 deletions ontologytimemachine/utils/proxy_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
OntoPrecedence,
OntoVersion,
HttpsInterception,
ClientConfigViaProxyAuth,
)


Expand Down Expand Up @@ -68,12 +69,24 @@ def get_response_from_request(wrapped_request, config):
# apply for current request
def evaluate_configuration(wrapped_request, config):
authentication_str = wrapped_request.get_authentication_from_request()
print(authentication_str)
username, password = authentication_str.split(":")
logger.info(username)
config_list = username.split(" ")
config = parse_arguments(config_list)
return config
if authentication_str:
logger.info("Authentication parameters provided, parsing the configuration.")
username, password = authentication_str.split(":")
logger.info(username)
config_list = username.split(" ")
config = parse_arguments(config_list)
return config
else:
if config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.OPTIONAL:
logger.info(
"Client configuration via proxy auth is optional, configuration not provided."
)
return None
elif config.clientConfigViaProxyAuth == ClientConfigViaProxyAuth.OPTIONAL:
logger.info(
"Client configuration via proxy auth is required btu configuration is not provided, return 500."
)
return None


def is_archivo_ontology_request(wrapped_request):
Expand Down Expand Up @@ -138,8 +151,6 @@ def request_ontology(url, headers, disableRemovingRedirects=False, timeout=5):
def proxy_logic(wrapped_request, config):
logger.info("Proxy has to intervene")

print(wrapped_request)
print(config)
set_onto_format_headers(wrapped_request, config)

headers = wrapped_request.get_request_headers()
Expand Down
1 change: 0 additions & 1 deletion ontologytimemachine/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ def map_mime_to_format(mime_type):


def set_onto_format_headers(wrapped_request, config):
print("here")
logger.info(
f"Setting headers based on ontoFormat: {config.ontoFormatConf} and ontoVersion: {config.ontoVersion}"
)
Expand Down
14 changes: 2 additions & 12 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,14 @@ def test_15_linked_web_apis():


def generic_test(iri, content_type):
response = requests.get(
iri,
proxies=PROXIES,
verify=CA_CERT_PATH,
auth=HTTPBasicAuth("admin", "archivo"),
)
response = requests.get(iri, proxies=PROXIES, verify=CA_CERT_PATH)
assert response.status_code == 200
assert iri in response.content.decode("utf-8")


def iri_generic_test(iri):
try:
response = requests.get(
iri,
proxies=PROXIES,
verify=CA_CERT_PATH,
auth=HTTPBasicAuth("admin", "archivo"),
)
response = requests.get(iri, proxies=PROXIES, verify=CA_CERT_PATH)
assert response.status_code == 200
assert iri in response.content.decode("utf-8")
except AssertionError:
Expand Down

0 comments on commit 60bfb9c

Please sign in to comment.