summaryrefslogtreecommitdiffstats
path: root/openstack/common/rootwrap/filters.py
diff options
context:
space:
mode:
authorDirk Mueller <dirk@dmllr.de>2013-06-19 00:08:57 +0200
committerDirk Mueller <dirk@dmllr.de>2013-06-20 14:36:43 +0200
commit3e74c0017e0b1ab209bc066cc0cec6c151b69b83 (patch)
tree22481be81a272bd94a9bc28a9a4baeff0c333852 /openstack/common/rootwrap/filters.py
parentfb13686a00e933c17bca163b51fb3d7119d34e5a (diff)
downloadoslo-3e74c0017e0b1ab209bc066cc0cec6c151b69b83.tar.gz
oslo-3e74c0017e0b1ab209bc066cc0cec6c151b69b83.tar.xz
oslo-3e74c0017e0b1ab209bc066cc0cec6c151b69b83.zip
Add IpFilter, IPNetnsExecFilter and EnvFilter
These filters have been implemented in Quantum before: - IpFilter provides support for filtering ip commands - IpNetnsExecFilter is a chaining command filter that verifies that the command to be executed by ip netns exec is covered by other established filters. IpNetnsExecFilter has been restricted to ensure that the filter chains have all matching filters run as the same user. EnvFilter is a new filter derived from CommandFilter that allows a Command to be optionally prefixed by "env" and a specific list of environment variables. This is intended to replace the specific DnsmasqFilter and DnsmasqNetnsFilter in the future when all consumers have been updated. Implements bp rootwrap-quantum-features Change-Id: I0cf39967126e99a8dc53d21bee824a0fe2f63aa0
Diffstat (limited to 'openstack/common/rootwrap/filters.py')
-rw-r--r--openstack/common/rootwrap/filters.py113
1 files changed, 113 insertions, 0 deletions
diff --git a/openstack/common/rootwrap/filters.py b/openstack/common/rootwrap/filters.py
index 0cc55ce..dfec412 100644
--- a/openstack/common/rootwrap/filters.py
+++ b/openstack/common/rootwrap/filters.py
@@ -235,3 +235,116 @@ class ReadFileFilter(CommandFilter):
if len(userargs) != 2:
return False
return True
+
+
+class IpFilter(CommandFilter):
+ """Specific filter for the ip utility to that does not match exec."""
+
+ def match(self, userargs):
+ if userargs[0] == 'ip':
+ if userargs[1] == 'netns':
+ return (userargs[2] in ('list', 'add', 'delete'))
+ else:
+ return True
+
+
+class EnvFilter(CommandFilter):
+ """Specific filter for the env utility.
+
+ Behaves like CommandFilter, except that it handles
+ leading env A=B.. strings appropriately.
+ """
+
+ def _extract_env(self, arglist):
+ """Extract all leading NAME=VALUE arguments from arglist."""
+
+ envs = set()
+ for arg in arglist:
+ if '=' not in arg:
+ break
+ envs.add(arg.partition('=')[0])
+ return envs
+
+ def __init__(self, exec_path, run_as, *args):
+ super(EnvFilter, self).__init__(exec_path, run_as, *args)
+
+ env_list = self._extract_env(self.args)
+ # Set exec_path to X when args are in the form of
+ # env A=a B=b C=c X Y Z
+ if "env" in exec_path and len(env_list) < len(self.args):
+ self.exec_path = self.args[len(env_list)]
+
+ def match(self, userargs):
+ # ignore leading 'env'
+ if userargs[0] == 'env':
+ userargs.pop(0)
+
+ # require one additional argument after configured ones
+ if len(userargs) < len(self.args):
+ return False
+
+ # extract all env args
+ user_envs = self._extract_env(userargs)
+ filter_envs = self._extract_env(self.args)
+ user_command = userargs[len(user_envs):len(user_envs) + 1]
+
+ # match first non-env argument with CommandFilter
+ return (super(EnvFilter, self).match(user_command)
+ and len(filter_envs) and user_envs == filter_envs)
+
+ def exec_args(self, userargs):
+ args = userargs[:]
+
+ # ignore leading 'env'
+ if args[0] == 'env':
+ args.pop(0)
+
+ # Throw away leading NAME=VALUE arguments
+ while args and '=' in args[0]:
+ args.pop(0)
+
+ return args
+
+ def get_command(self, userargs, exec_dirs=[]):
+ to_exec = self.get_exec(exec_dirs=exec_dirs) or self.exec_path
+ return [to_exec] + self.exec_args(userargs)[1:]
+
+ def get_environment(self, userargs):
+ env = os.environ.copy()
+
+ # ignore leading 'env'
+ if userargs[0] == 'env':
+ userargs.pop(0)
+
+ # Handle leading NAME=VALUE pairs
+ for a in userargs:
+ env_name, equals, env_value = a.partition('=')
+ if not equals:
+ break
+ if env_name and env_value:
+ env[env_name] = env_value
+
+ return env
+
+
+class ChainingFilter(CommandFilter):
+ def exec_args(self, userargs):
+ return []
+
+
+class IpNetnsExecFilter(ChainingFilter):
+ """Specific filter for the ip utility to that does match exec."""
+
+ def match(self, userargs):
+ # Network namespaces currently require root
+ # require <ns> argument
+ if self.run_as != "root" or len(userargs) < 4:
+ return False
+
+ return (userargs[:3] == ['ip', 'netns', 'exec'])
+
+ def exec_args(self, userargs):
+ args = userargs[4:]
+ if args:
+ args[0] = os.path.basename(args[0])
+ return args