Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions osc_sdk_python/authentication.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from requests.structures import CaseInsensitiveDict
import datetime
import hashlib
import hmac
import base64
import requests

from .version import get_version
from .credentials import Profile
Expand Down Expand Up @@ -174,3 +176,17 @@ def get_basic_auth_header(self):
"X-Osc-Date": date_iso,
"Authorization": "Basic " + b64_creds,
}

def __call__(self, request: requests.PreparedRequest) -> requests.PreparedRequest:
if self.is_basic_auth_configured():
auth_headers = self.get_basic_auth_header()
else:
auth_headers = self.forge_headers_signed(request.path_url, request.body or "")

if request.headers is None:
request.headers = CaseInsensitiveDict()

for head in auth_headers:
request.headers[head] = auth_headers[head]

return request
3 changes: 1 addition & 2 deletions osc_sdk_python/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def __init__(self, logger=None, limiter=None, **kwargs):
self.limiter: RateLimiter | None = limiter
self.retry_kwargs = {}
self.session = Session()
self.session.trust_env = False

kwargs = self.update_limiter(**kwargs)
kwargs = self.update_retry(**kwargs)
Expand Down Expand Up @@ -88,7 +87,7 @@ def api(self, action, service="api", **data):
self.logger.do_log(
"uri: " + uri + "\npayload:\n" + json.dumps(data, indent=2)
)
return requester.send(uri, json.dumps(data))
return requester.send(json.dumps(data))
except Exception as err:
raise err

Expand Down
11 changes: 2 additions & 9 deletions osc_sdk_python/requester.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
from .retry import Retry


class Requester:
def __init__(self, session, auth, endpoint, **kwargs):
self.session = session
self.auth = auth
self.endpoint = endpoint
self.request_kwargs = kwargs

def send(self, uri, payload):
headers = None
if self.auth.is_basic_auth_configured():
headers = self.auth.get_basic_auth_header()
else:
headers = self.auth.forge_headers_signed(uri, payload)

def send(self, payload):
if self.auth.x509_client_cert is not None:
cert_file = self.auth.x509_client_cert
else:
cert_file = None

retry_kwargs = self.request_kwargs.copy()
retry_kwargs.update(
{"data": payload, "headers": headers, "verify": True, "cert": cert_file}
{"data": payload, "auth": self.auth, "verify": True, "cert": cert_file}
)

response = Retry(self.session, "post", self.endpoint, **retry_kwargs)
Expand Down
78 changes: 78 additions & 0 deletions tests/test_proxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import os
import unittest
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
import unittest.mock

from osc_sdk_python.call import Call
from osc_sdk_python.credentials import Profile


class TestProxySupport(unittest.TestCase):
def test_proxy_env_passed_to_session(self):
with unittest.mock.patch.object(
Profile, "from_standard_configuration"
) as mock_from_std:
mock_from_std.return_value = Profile(region="eu-west-2", protocol="https")

with unittest.mock.patch.dict(
os.environ, {"HTTPS_PROXY": "http://proxy.example.com:8080"}
):
call = Call(access_key="fake-ak", secret_key="fake-sk")

captured_proxies = []

class FakeAdapter:
def send(self, request, **kwargs):
captured_proxies.append(kwargs.get("proxies"))
import requests

resp = requests.Response()
resp.status_code = 200
resp._content = b'{"status": "ok"}'
resp.request = request
resp.url = request.url
return resp

call.session.mount("https://", FakeAdapter())

result = call.api("ReadVms")

self.assertEqual(len(captured_proxies), 1)
self.assertEqual(
captured_proxies[0],
{"https": "http://proxy.example.com:8080"},
)
self.assertEqual(result, {"status": "ok"})

def test_no_proxy_env_no_proxies_kwarg(self):
with unittest.mock.patch.object(
Profile, "from_standard_configuration"
) as mock_from_std:
mock_from_std.return_value = Profile(region="eu-west-2", protocol="https")

with unittest.mock.patch.dict(os.environ, {}, clear=True):
call = Call(access_key="fake-ak", secret_key="fake-sk")

captured_proxies = []

class FakeAdapter:
def send(self, request, **kwargs):
captured_proxies.append(kwargs.get("proxies"))
import requests

resp = requests.Response()
resp.status_code = 200
resp._content = b'{"status": "ok"}'
resp.request = request
resp.url = request.url
return resp

call.session.mount("https://", FakeAdapter())

call.api("ReadVms")

self.assertEqual(len(captured_proxies), 1)
self.assertEqual(captured_proxies[0], {})


if __name__ == "__main__":
unittest.main()
Loading