summaryrefslogtreecommitdiffstats
path: root/xlators/features
diff options
context:
space:
mode:
authorCsaba Henk <csaba@gluster.com>2011-09-20 16:20:18 +0200
committerVijay Bellur <vijay@gluster.com>2011-09-22 05:24:41 -0700
commitb27b9d36de798bb18eaa95524f3900f9e17ce3e5 (patch)
tree7357344c289afee7a196fbc8d01b4f56ae2a5d86 /xlators/features
parentd7c9d2bfbd20727f90b0118c982ff9612aacacf2 (diff)
geo-rep: implement IP address based access control
- gsyncd gets allow-network tunable which is expected to hold a comma-separated list of IP network addresses - for IP addess matching, bring in ipaddr module from Google (http://code.google.com/p/ipaddr-py/, rev. trunk@225) This will let users control master's access to slave's volumes until we implement unprivileged geo-rep (delayed due to some technical issues). It's also needed for the completeness of our hardening efforts, as plain file slaves won't be able to work with an unprivileged gsyncd. Change-Id: I58431cba6592f8672e93ea89a5eef478905b00b9 BUG: 2825 Reviewed-on: http://review.gluster.com/488 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vijay@gluster.com>
Diffstat (limited to 'xlators/features')
-rw-r--r--xlators/features/marker/utils/syncdaemon/Makefile.am3
-rw-r--r--xlators/features/marker/utils/syncdaemon/__codecheck.py61
-rw-r--r--xlators/features/marker/utils/syncdaemon/gsyncd.py23
3 files changed, 64 insertions, 23 deletions
diff --git a/xlators/features/marker/utils/syncdaemon/Makefile.am b/xlators/features/marker/utils/syncdaemon/Makefile.am
index ef2dc9aea..cc7cee102 100644
--- a/xlators/features/marker/utils/syncdaemon/Makefile.am
+++ b/xlators/features/marker/utils/syncdaemon/Makefile.am
@@ -1,5 +1,6 @@
syncdaemondir = $(libexecdir)/glusterfs/python/syncdaemon
-syncdaemon_PYTHON = gconf.py gsyncd.py __init__.py master.py README.md repce.py resource.py configinterface.py syncdutils.py monitor.py libcxattr.py
+syncdaemon_PYTHON = gconf.py gsyncd.py __init__.py master.py README.md repce.py resource.py configinterface.py syncdutils.py monitor.py libcxattr.py \
+ $(top_builddir)/contrib/ipaddr-py/ipaddr.py
CLEANFILES =
diff --git a/xlators/features/marker/utils/syncdaemon/__codecheck.py b/xlators/features/marker/utils/syncdaemon/__codecheck.py
index 832e75c44..e3386afba 100644
--- a/xlators/features/marker/utils/syncdaemon/__codecheck.py
+++ b/xlators/features/marker/utils/syncdaemon/__codecheck.py
@@ -1,27 +1,46 @@
import os
import os.path
import sys
+import tempfile
+import shutil
-fl = os.listdir(os.path.dirname(sys.argv[0]) or '.')
-fl.sort()
-for f in fl:
- if f[-3:] != '.py' or f[0] == '_':
- continue
- m = f[:-3]
- sys.stdout.write('importing %s ...' % m)
- __import__(m)
- print(' OK.')
+ipd = tempfile.mkdtemp(prefix = 'codecheck-aux')
-def sys_argv_set(a):
- sys.argv = sys.argv[:1] + a
+try:
+ # add a fake ipaddr module, we don't want to
+ # deal with the real one (just test our code)
+ f = open(os.path.join(ipd, 'ipaddr.py'), 'w')
+ f.write("""
+class IPAddress(object):
+ pass
+class IPNetwork(list):
+ pass
+""")
+ f.close()
+ sys.path.append(ipd)
-gsyncd = sys.modules['gsyncd']
-for a in [['--help'], ['--version'], ['--canonicalize-escape-url', '/foo']]:
- print('>>> invoking program with args: %s' % ' '.join(a))
- pid = os.fork()
- if not pid:
- sys_argv_set(a)
- gsyncd.main()
- _, r = os.waitpid(pid, 0)
- if r:
- raise RuntimeError('invocation failed')
+ fl = os.listdir(os.path.dirname(sys.argv[0]) or '.')
+ fl.sort()
+ for f in fl:
+ if f[-3:] != '.py' or f[0] == '_':
+ continue
+ m = f[:-3]
+ sys.stdout.write('importing %s ...' % m)
+ __import__(m)
+ print(' OK.')
+
+ def sys_argv_set(a):
+ sys.argv = sys.argv[:1] + a
+
+ gsyncd = sys.modules['gsyncd']
+ for a in [['--help'], ['--version'], ['--canonicalize-escape-url', '/foo']]:
+ print('>>> invoking program with args: %s' % ' '.join(a))
+ pid = os.fork()
+ if not pid:
+ sys_argv_set(a)
+ gsyncd.main()
+ _, r = os.waitpid(pid, 0)
+ if r:
+ raise RuntimeError('invocation failed')
+finally:
+ shutil.rmtree(ipd)
diff --git a/xlators/features/marker/utils/syncdaemon/gsyncd.py b/xlators/features/marker/utils/syncdaemon/gsyncd.py
index 9771822dc..f3b5988ad 100644
--- a/xlators/features/marker/utils/syncdaemon/gsyncd.py
+++ b/xlators/features/marker/utils/syncdaemon/gsyncd.py
@@ -13,6 +13,8 @@ from optparse import OptionParser, SUPPRESS_HELP
from logging import Logger
from errno import EEXIST, ENOENT
+from ipaddr import IPAddress, IPNetwork
+
from gconf import gconf
from syncdutils import FreeObject, norm, grabpidfile, finalize, log_raise_exception
from syncdutils import GsyncdError
@@ -159,6 +161,7 @@ def main_i():
op.add_option('--timeout', metavar='SEC', type=int, default=120)
op.add_option('--sync-jobs', metavar='N', type=int, default=3)
op.add_option('--turns', metavar='N', type=int, default=0, help=SUPPRESS_HELP)
+ op.add_option('--allow-network', metavar='IPS', default='')
op.add_option('-c', '--config-file', metavar='CONF', type=str, action='callback', callback=store_local)
# duh. need to specify dest or value will be mapped to None :S
@@ -208,7 +211,9 @@ def main_i():
sys.stderr.write(op.get_usage() + "\n")
sys.exit(1)
- if os.getenv('_GSYNCD_RESTRICTED_'):
+ restricted = os.getenv('_GSYNCD_RESTRICTED_')
+
+ if restricted:
allopts = {}
allopts.update(opts.__dict__)
allopts.update(rconf)
@@ -288,6 +293,22 @@ def main_i():
gconf.__dict__.update(opts.__dict__)
gconf.configinterface = gcnf
+ if restricted and gconf.allow_network:
+ ssh_conn = os.getenv('SSH_CONNECTION')
+ if not ssh_conn:
+ #legacy env var
+ ssh_conn = os.getenv('SSH_CLIENT')
+ if ssh_conn:
+ allowed_networks = [ IPNetwork(a) for a in gconf.allow_network.split(',') ]
+ client_ip = IPAddress(ssh_conn.split()[0])
+ allowed = False
+ for nw in allowed_networks:
+ if client_ip in nw:
+ allowed = True
+ break
+ if not allowed:
+ raise GsyncdError("client IP address is not allowed")
+
ffd = rconf.get('feedback_fd')
if ffd:
fcntl.fcntl(ffd, fcntl.F_SETFD, fcntl.FD_CLOEXEC)