Skip to content

Commit

Permalink
pylxd/client: Unix socket connection without requests_unixsocket
Browse files Browse the repository at this point in the history
Implementation inspired by `request_unixsocket` own implementation:
https://github.com/msabramo/requests-unixsocket/blob/master/requests_unixsocket/adapters.py
Method `get_connection_with_tls_context` introduced for compatibility
with later `requests` versions, but keeping old `get_connections` to
retain compatibility with previously used versions.
Keeping this does not imply in a security vulnerability as TLS authentication is
not required for Unix Socket connections.

Signed-off-by: hamistao <[email protected]>
  • Loading branch information
hamistao committed Oct 1, 2024
1 parent 0f102cb commit 2253741
Showing 1 changed file with 69 additions and 7 deletions.
76 changes: 69 additions & 7 deletions pylxd/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@
import json
import os
import re
import socket
from enum import Enum
from typing import NamedTuple
from urllib import parse

import requests
import requests_unixsocket
import requests.adapters
import urllib3
import urllib3.connection
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from ws4py.client import WebSocketBaseClient

from pylxd import exceptions, managers

requests_unixsocket.monkeypatch()

SNAP_ROOT = os.path.expanduser("~/snap/lxd/common/config/")
APT_ROOT = os.path.expanduser("~/.config/lxc/")
CERT_FILE_NAME = "client.crt"
Expand All @@ -51,6 +52,9 @@ class Cert(NamedTuple):
key=os.path.join(CERTS_PATH, KEY_FILE_NAME),
) # pragma: no cover

DEFAULT_SCHEME = "http+unix://"
SOCKET_CONNECTION_TIMEOUT = 60


class EventType(Enum):
All = "all"
Expand All @@ -59,6 +63,65 @@ class EventType(Enum):
Lifecycle = "lifecycle"


class _UnixSocketHTTPConnection(urllib3.connection.HTTPConnection, object):
def __init__(self, unix_socket_url):
super(_UnixSocketHTTPConnection, self).__init__(
"localhost", timeout=SOCKET_CONNECTION_TIMEOUT
)
self.unix_socket_url = unix_socket_url
self.timeout = SOCKET_CONNECTION_TIMEOUT
self.sock = None

def __del__(self):
if self.sock:
self.sock.close()

def connect(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
socket_path = parse.unquote(parse.urlparse(self.unix_socket_url).netloc)
sock.connect(socket_path)
self.sock = sock


class _UnixSocketHTTPConnectionPool(urllib3.HTTPConnectionPool):
def __init__(self, socket_path):
super(_UnixSocketHTTPConnectionPool, self).__init__("localhost")
self.socket_path = socket_path

def _new_conn(self):
return _UnixSocketHTTPConnection(self.socket_path)


class _UnixAdapter(requests.adapters.HTTPAdapter):
def __init__(self, pool_connections=25, *args, **kwargs):
super(_UnixAdapter, self).__init__(*args, **kwargs)
self.pools = urllib3._collections.RecentlyUsedContainer(
pool_connections, dispose_func=lambda p: p.close()
)

def get_connection(self, url, proxies):
with self.pools.lock:
conn = self.pools.get(url)
if conn:
return conn

conn = _UnixSocketHTTPConnectionPool(url)
self.pools[url] = conn

return conn

# This method is needed fo compatibility with later requests versions.
def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
return self.get_connection(request.url, None)

def request_url(self, request, proxies):
return request.path_url

def close(self):
self.pools.clear()


class LXDSSLAdapter(requests.adapters.HTTPAdapter):
def cert_verify(self, conn, url, verify, cert):
with open(verify, "rb") as fd:
Expand All @@ -74,11 +137,10 @@ def get_session_for_url(url: str, verify=None, cert=None) -> requests.Session:
Call sites can use this to customise the session before passing into a Client.
"""
session: requests.Session
if url.startswith("http+unix://"):
session = requests_unixsocket.Session()
session = requests.Session()
if url.startswith(DEFAULT_SCHEME):
session.mount(DEFAULT_SCHEME, _UnixAdapter())
else:
session = requests.Session()
session.cert = cert
session.verify = verify

Expand Down

0 comments on commit 2253741

Please sign in to comment.