Skip to content
Open
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
14 changes: 10 additions & 4 deletions kubernetes/stream/ws_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,16 @@ def websocket_proxycare(connect_opt, configuration, url, headers):
if configuration.proxy_headers:
for key,value in configuration.proxy_headers.items():
if key == 'proxy-authorization' and value.startswith('Basic'):
b64value = value.split()[1]
auth = urlsafe_b64decode(b64value).decode().split(':', 1)
if len(auth) == 2:
connect_opt.update({'http_proxy_auth': (auth[0], auth[1]) })
parts = value.split()
if len(parts) < 2:
raise ApiValueError(
"Invalid proxy-authorization header: missing Basic credentials")
auth = urlsafe_b64decode(parts[1]).decode().split(':', 1)
if len(auth) != 2:
raise ApiValueError(
"Invalid proxy-authorization header: Basic credentials "
"must be in the form 'user:password'")
connect_opt.update({'http_proxy_auth': (auth[0], auth[1]) })
return(connect_opt)


Expand Down
12 changes: 11 additions & 1 deletion kubernetes/stream/ws_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .ws_client import get_websocket_url, WSClient, V5_CHANNEL_PROTOCOL, V4_CHANNEL_PROTOCOL, CLOSE_CHANNEL, STDIN_CHANNEL, STDOUT_CHANNEL
from .ws_client import websocket_proxycare
from kubernetes.client.configuration import Configuration
from kubernetes.client.rest import ApiValueError
import os
import select
import socket
Expand Down Expand Up @@ -112,7 +113,6 @@ def test_websocket_proxycare(self):
( 'http://proxy.example.com:8080/', 'user:pass', '.example.com', 'proxy.example.com', 8080, ('user','pass'), ['.example.com']),
( 'http://proxy.example.com:8080/', 'user:pass', 'localhost,.local,.example.com', 'proxy.example.com', 8080, ('user','pass'), ['localhost','.local','.example.com']),
( 'http://proxy.example.com:8080/', 'user:pa:ss:word', None, 'proxy.example.com', 8080, ('user','pa:ss:word'), None),
( 'http://proxy.example.com:8080/', 'useronly', None, 'proxy.example.com', 8080, None, None),
]:
# input setup
cfg = Configuration(proxy='', no_proxy='')
Expand All @@ -130,6 +130,16 @@ def test_websocket_proxycare(self):
assert dictval(connect_opts, 'http_proxy_auth') == expect_auth
assert dictval(connect_opts, 'http_no_proxy') == expect_noproxy

def test_websocket_proxycare_invalid_basic_credentials(self):
for proxy_auth in [
urllib3.util.make_headers(proxy_basic_auth='useronly')['proxy-authorization'],
'Basic',
]:
cfg = Configuration(proxy='http://proxy.example.com:8080/', no_proxy='')
cfg.proxy_headers = {'proxy-authorization': proxy_auth}
with self.assertRaises(ApiValueError):
websocket_proxycare({}, cfg, None, None)


class WSClientMultiFrameReadTest(unittest.TestCase):
"""Tests that reads spanning multiple websocket frames are not
Expand Down
Loading