2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-05-18 12:17:17 +00:00

Permit override of unix ownership/permissions on sockets

If an environment knows more specifically what should have access in terms of group, allow service.cfg to indicate.
This commit is contained in:
Jarrod Johnson
2026-05-07 08:44:16 -04:00
parent 01cc86fa55
commit c69952265f
3 changed files with 32 additions and 15 deletions
+14 -4
View File
@@ -17,6 +17,7 @@
# This SCGI server provides a http wrap to confluent api
# It additionally manages httprequest console sessions
import base64
import shutil
try:
import Cookie
except ModuleNotFoundError:
@@ -1217,7 +1218,7 @@ def _assemble_json(responses, resource=None, url=None, extension=None):
rspdata, sort_keys=True, indent=4, ensure_ascii=False).encode('utf-8'))
def serve(bind_host, bind_port):
def serve(bind_host, bind_port, bind_group=None, bind_perms=None):
# TODO(jbjohnso): move to unix socket and explore
# either making apache deal with it
# or just supporting nginx or lighthttpd
@@ -1232,13 +1233,17 @@ def serve(bind_host, bind_port):
while not sock:
try:
if '/' in bind_host:
oldumask = os.umask(0o777 - bind_perms)
try:
os.remove(bind_host)
except Exception:
pass
sock = eventlet.listen(
bind_host, family=socket.AF_UNIX)
os.chmod(bind_host, 0o666)
os.umask(oldumask)
os.chmod(bind_host, bind_perms)
if bind_group:
shutil.chown(bind_host, group=bind_group)
else:
addrinfo = socket.getaddrinfo(bind_host, bind_port)[0]
sock = eventlet.listen(
@@ -1264,17 +1269,22 @@ def serve(bind_host, bind_port):
class HttpApi(object):
def __init__(self, bind_host=None, bind_port=None):
def __init__(self, bind_host=None, bind_port=None, bind_group=None, bind_perms=None):
self.server = None
self.bind_host = bind_host or '127.0.0.1'
self.bind_port = bind_port or 4005
# Ultimately, a unix socket is being used in lieu of a TCP socket,
# so open permissions make sense as the security is not based solely on socket access
# however, steering it to webserver group can be done for extra confidence
self.bind_group = bind_group
self.bind_perms = bind_perms or 0o666
def start(self):
global auditlog
global tracelog
tracelog = log.Logger('trace')
auditlog = log.Logger('audit')
self.server = eventlet.spawn(serve, self.bind_host, self.bind_port)
self.server = eventlet.spawn(serve, self.bind_host, self.bind_port, self.bind_group, self.bind_perms)
_cleaner = eventlet.spawn(_sessioncleaner)
+7 -5
View File
@@ -314,14 +314,14 @@ def run(args):
auth.check_for_yaml()
collective.startup()
consoleserver.initialize()
http_bind_host, http_bind_port = _get_connector_config('http')
sock_bind_host, sock_bind_port = _get_connector_config('socket')
http_bind_host, http_bind_port, http_bind_group, http_bind_perms = _get_connector_config('http')
sock_bind_host, sock_bind_port, sock_bind_group, sock_bind_perms = _get_connector_config('socket')
try:
sockservice = sockapi.SockApi(sock_bind_host, sock_bind_port)
sockservice = sockapi.SockApi(sock_bind_host, sock_bind_port, sock_bind_group, sock_bind_perms)
sockservice.start()
except NameError:
pass
webservice = httpapi.HttpApi(http_bind_host, http_bind_port)
webservice = httpapi.HttpApi(http_bind_host, http_bind_port, http_bind_group, http_bind_perms)
webservice.start()
while len(list(configmanager.list_collective())) >= 2:
# If in a collective, stall automatic startup activity
@@ -340,7 +340,9 @@ def run(args):
def _get_connector_config(session):
host = conf.get_option(session, 'bindhost')
port = conf.get_int_option(session, 'bindport')
return (host, port)
group = conf.get_option(session, 'bindgroup')
perms = conf.get_option(session, 'bindperms')
return (host, port, group, perms)
def _get_logdirectory():
return conf.get_option('globals', 'logdirectory')
+11 -6
View File
@@ -26,6 +26,7 @@ import ctypes.util
import errno
import os
import pwd
import shutil
import stat
import struct
import sys
@@ -458,7 +459,7 @@ def removesocket():
except OSError:
pass
def _unixdomainhandler():
def _unixdomainhandler(bind_group=None, bind_perms=None):
unixsocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
os.remove("/var/run/confluent/api.sock")
@@ -466,10 +467,12 @@ def _unixdomainhandler():
pass
if not os.path.isdir("/var/run/confluent"):
os.makedirs('/var/run/confluent', 0o755)
oldumask = os.umask(0o777 - bind_perms)
unixsocket.bind("/var/run/confluent/api.sock")
os.chmod("/var/run/confluent/api.sock",
stat.S_IWOTH | stat.S_IROTH | stat.S_IWGRP |
stat.S_IRGRP | stat.S_IWUSR | stat.S_IRUSR)
os.chmod("/var/run/confluent/api.sock", bind_perms)
if bind_group:
shutil.chown("/var/run/confluent/api.sock", group=bind_group)
os.umask(oldumask)
atexit.register(removesocket)
unixsocket.listen(5)
while True:
@@ -498,11 +501,13 @@ def _unixdomainhandler():
class SockApi(object):
def __init__(self, bindhost=None, bindport=None):
def __init__(self, bindhost=None, bindport=None, bind_group=None, bind_perms=None):
self.tlsserver = None
self.unixdomainserver = None
self.bind_host = bindhost or '::'
self.bind_port = bindport or 13001
self.bind_group = bind_group
self.bind_perms = bind_perms or 0o666
def start(self):
global auditlog
@@ -515,7 +520,7 @@ class SockApi(object):
else:
eventlet.spawn_n(self.watch_for_cert)
eventlet.spawn_n(self.watch_resolv)
self.unixdomainserver = eventlet.spawn(_unixdomainhandler)
self.unixdomainserver = eventlet.spawn(_unixdomainhandler, self.bind_group, self.bind_perms)
def watch_resolv(self):
while True: