Skip to content
This repository was archived by the owner on Sep 26, 2019. It is now read-only.

Commit df60b50

Browse files
author
Alessio Ababilov
committed
Do not change process UID
When run with sudo, Anvil changed process real UID to SUDO_UID thus easily creating files with different owners. This mechanism can confuse some tools (like pip) Now, we can almost safely stop changing real UID and run prepare as non-root and bootstrap, install, start, status, and stop as root. Also, this removes dependency on sudo. Implements: blueprint no-uid-tricks Fixes: bug #1179747 Fixes: bug #1186440 Fixes: bug #1186448 Change-Id: I7ae293aad7f0a5ba08962e6b6b709fe49b8b81ec
1 parent 8b06edd commit df60b50

File tree

27 files changed

+254
-351
lines changed

27 files changed

+254
-351
lines changed

anvil/__main__.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@ def ensure_anvil_dirs(root_dir):
148148
if sh.isdir(d):
149149
continue
150150
LOG.info("Creating anvil directory at path: %s", d)
151-
with sh.Rooted(True):
152-
sh.mkdir(d, adjust_suids=True)
151+
sh.mkdir(d)
153152

154153

155154
def store_current_settings(c_settings):
@@ -159,14 +158,11 @@ def store_current_settings(c_settings):
159158
for k in ['action', 'verbose', 'dryrun']:
160159
if k in c_settings:
161160
to_save.pop(k, None)
162-
with sh.Rooted(True):
163-
with open("/etc/anvil/settings.yaml", 'w') as fh:
164-
fh.write("# Anvil last used settings\n")
165-
fh.write(utils.add_header("/etc/anvil/settings.yaml",
166-
utils.prettify_yaml(to_save)))
167-
fh.flush()
168-
(uid, gid) = sh.get_suids()
169-
sh.chown("/etc/anvil/settings.yaml", uid, gid)
161+
with open("/etc/anvil/settings.yaml", 'w') as fh:
162+
fh.write("# Anvil last used settings\n")
163+
fh.write(utils.add_header("/etc/anvil/settings.yaml",
164+
utils.prettify_yaml(to_save)))
165+
fh.flush()
170166
except Exception as e:
171167
LOG.debug("Failed writing to %s due to %s", "/etc/anvil/settings.yaml", e)
172168

@@ -175,8 +171,6 @@ def ensure_perms():
175171
# Ensure we are running as root to start...
176172
if not sh.got_root():
177173
raise excp.PermException("Root access required")
178-
# Drop to usermode (which also ensures we can do this...)
179-
sh.user_mode(quiet=False)
180174

181175

182176
def main():

anvil/components/base_install.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ def __init__(self, *args, **kargs):
177177
super(PkgUninstallComponent, self).__init__(*args, **kargs)
178178
trace_fn = tr.trace_filename(self.get_option('trace_dir'), 'created')
179179
self.tracereader = tr.TraceReader(trace_fn)
180-
self.purge_packages = kargs.get('purge_packages')
181180

182181
def unconfigure(self):
183182
self._unconfigure_links()
@@ -188,7 +187,7 @@ def _unconfigure_links(self):
188187
utils.log_iterable(sym_files, logger=LOG,
189188
header="Removing %s symlink files" % (len(sym_files)))
190189
for fn in sym_files:
191-
sh.unlink(fn, run_as_root=True)
190+
sh.unlink(fn)
192191

193192
def post_uninstall(self):
194193
self._uninstall_files()
@@ -203,7 +202,7 @@ def _uninstall_files(self):
203202
utils.log_iterable(files_touched, logger=LOG,
204203
header="Removing %s miscellaneous files" % (len(files_touched)))
205204
for fn in files_touched:
206-
sh.unlink(fn, run_as_root=True)
205+
sh.unlink(fn)
207206

208207
def _uninstall_dirs(self):
209208
dirs_made = self.tracereader.dirs_made()
@@ -212,4 +211,4 @@ def _uninstall_dirs(self):
212211
utils.log_iterable(dirs_alive, logger=LOG,
213212
header="Removing %s created directories" % (len(dirs_alive)))
214213
for dir_name in dirs_alive:
215-
sh.deldir(dir_name, run_as_root=True)
214+
sh.deldir(dir_name)

anvil/components/base_testing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def run_tests(self):
135135
if self.get_bool_option("verbose", default_value=False):
136136
null_fh = None
137137
try:
138-
sh.execute(*cmd, stdout_fh=None, stderr_fh=null_fh, cwd=app_dir, env_overrides=env)
138+
sh.execute(cmd, stdout_fh=None, stderr_fh=null_fh, cwd=app_dir, env_overrides=env)
139139
except excp.ProcessExecutionError as e:
140140
if self.get_bool_option("ignore-test-failures", default_value=False):
141141
LOG.warn("Ignoring test failure of component %s: %s", colorizer.quote(self.name), e)

anvil/components/cinder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def post_install(self):
4545

4646
def _sync_db(self):
4747
LOG.info("Syncing cinder to database: %s", colorizer.quote(self.configurator.DB_NAME))
48-
cmds = [{'cmd': SYNC_DB_CMD, 'run_as_root': True}]
48+
cmds = [{'cmd': SYNC_DB_CMD}]
4949
utils.execute_template(*cmds, cwd=self.bin_dir, params=self.config_params(None))
5050

5151
def config_params(self, config_fn):

anvil/components/configurators/glance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def _config_adjust_api(self, config):
7272
LOG.debug("Ensuring file system store directory %r exists and is empty." % (img_store_dir))
7373
if sh.isdir(img_store_dir):
7474
sh.deldir(img_store_dir)
75-
sh.mkdirslist(img_store_dir, tracewriter=self.installer.tracewriter, adjust_suids=True)
75+
sh.mkdirslist(img_store_dir, tracewriter=self.installer.tracewriter)
7676

7777
def _config_adjust_reg(self, config):
7878
self._config_adjust_api_reg(config)

anvil/components/db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _run_action(self, action, check_exit_code=True):
154154
cmd = self._get_command(action)
155155
if not cmd:
156156
raise NotImplementedError("No distro command provided to perform action %r" % (action))
157-
return sh.execute(*cmd, run_as_root=True, check_exit_code=check_exit_code)
157+
return sh.execute(cmd, check_exit_code=check_exit_code)
158158

159159
def start(self):
160160
if self.statii()[0].status != bruntime.STATUS_STARTED:

anvil/components/glance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def post_install(self):
5252

5353
def _sync_db(self):
5454
LOG.info("Syncing glance to database: %s", colorizer.quote(self.configurator.DB_NAME))
55-
cmds = [{'cmd': SYNC_DB_CMD, 'run_as_root': True}]
55+
cmds = [{'cmd': SYNC_DB_CMD}]
5656
utils.execute_template(*cmds, cwd=self.bin_dir, params=self.config_params(None))
5757

5858
@property

anvil/components/helpers/db.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def drop_db(distro, dbtype, user, pw, dbname, **kwargs):
4646
cmds = list()
4747
cmds.append({
4848
'cmd': dropcmd,
49-
'run_as_root': False,
5049
})
5150
utils.execute_template(*cmds, params=params)
5251
else:
@@ -67,7 +66,6 @@ def create_db(distro, dbtype, user, pw, dbname, **kwargs):
6766
cmds = list()
6867
cmds.append({
6968
'cmd': createcmd,
70-
'run_as_root': False,
7169
})
7270
utils.execute_template(*cmds, params=params)
7371
else:

anvil/components/helpers/nova.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ def _stop_dnsmasq(self):
9393
continue
9494
cwd = ''
9595
cmdline = ''
96-
with sh.Rooted(True):
97-
cwd = proc.getcwd()
98-
cmdline = " ".join(proc.cmdline)
96+
cwd = proc.getcwd()
97+
cmdline = " ".join(proc.cmdline)
9998
to_try = False
10099
for t in [cwd, cmdline]:
101100
if t.lower().find("nova") != -1:
@@ -107,8 +106,7 @@ def _stop_dnsmasq(self):
107106
header="Killing leftover nova dnsmasq processes with process ids",
108107
logger=nconf.LOG)
109108
for pid in to_kill:
110-
with sh.Rooted(True):
111-
sh.kill(pid)
109+
sh.kill(pid)
112110

113111
def _clean_iptables(self):
114112
# Nova doesn't seem to cleanup its iptables rules that it
@@ -136,7 +134,7 @@ def translate_rule(line, start_search, start_replace):
136134
# Isolate the nova rules
137135
clean_rules = []
138136
list_cmd = ['iptables', '--list-rules', '--verbose']
139-
(stdout, _stderr) = sh.execute(*list_cmd, run_as_root=True)
137+
(stdout, _stderr) = sh.execute(list_cmd)
140138
for line in stdout.splitlines():
141139
line = line.strip()
142140
if not line_matcher(line, "-A"):
@@ -149,7 +147,7 @@ def translate_rule(line, start_search, start_replace):
149147
# Isolate the nova nat rules
150148
clean_nats = []
151149
nat_cmd = ['iptables', '--list-rules', '--verbose', '--table', 'nat']
152-
(stdout, _stderr) = sh.execute(*nat_cmd, run_as_root=True)
150+
(stdout, _stderr) = sh.execute(nat_cmd)
153151
for line in stdout.splitlines():
154152
line = line.strip()
155153
if not line_matcher(line, "-A"):
@@ -162,7 +160,7 @@ def translate_rule(line, start_search, start_replace):
162160
# Isolate the nova chains
163161
clean_chains = []
164162
chain_cmd = ['iptables', '--list-rules', '--verbose']
165-
(stdout, _stderr) = sh.execute(*chain_cmd, run_as_root=True)
163+
(stdout, _stderr) = sh.execute(chain_cmd)
166164
for line in stdout.splitlines():
167165
if not line_matcher(line, "-N"):
168166
continue
@@ -174,7 +172,7 @@ def translate_rule(line, start_search, start_replace):
174172
# Isolate the nova nat chains
175173
clean_nat_chains = []
176174
nat_chain_cmd = ['iptables', '--list-rules', '--verbose', '--table', 'nat']
177-
(stdout, _stderr) = sh.execute(*nat_chain_cmd, run_as_root=True)
175+
(stdout, _stderr) = sh.execute(nat_chain_cmd)
178176
for line in stdout.splitlines():
179177
if not line_matcher(line, "-N"):
180178
continue
@@ -187,11 +185,11 @@ def translate_rule(line, start_search, start_replace):
187185
for r in clean_rules + clean_chains:
188186
pieces = r.split(None)
189187
pieces = ['iptables'] + pieces
190-
sh.execute(*pieces, run_as_root=True, shell=True)
188+
sh.execute(pieces, shell=True)
191189
for r in clean_nats + clean_nat_chains:
192190
pieces = r.split(None)
193191
pieces = ['iptables', '--table', 'nat'] + pieces
194-
sh.execute(*pieces, run_as_root=True, shell=True)
192+
sh.execute(pieces, shell=True)
195193

196194
def clean(self):
197195
self._stop_dnsmasq()

anvil/components/helpers/virt.py

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def __init__(self, service_wait, distro):
5959

6060
def _service_status(self):
6161
cmd = self.distro.get_command('libvirt', 'status')
62-
(stdout, stderr) = sh.execute(*cmd, run_as_root=True, check_exit_code=False)
62+
(stdout, stderr) = sh.execute(cmd, check_exit_code=False)
6363
combined = (stdout + stderr)
6464
if combined.lower().find("running") != -1 or combined.lower().find('start') != -1:
6565
return (_ALIVE, combined)
@@ -78,7 +78,7 @@ def _destroy_domain(self, libvirt, conn, dom_name):
7878

7979
def restart_service(self):
8080
cmd = self.distro.get_command('libvirt', 'restart')
81-
sh.execute(*cmd, run_as_root=True)
81+
sh.execute(cmd)
8282

8383
def wait_active(self):
8484
# TODO(harlowja) fix this by using the component wait active...
@@ -99,7 +99,6 @@ def check_virt(self, virt_type):
9999
self.wait_active()
100100
cmds = [{
101101
'cmd': self.distro.get_command('libvirt', 'verify'),
102-
'run_as_root': True,
103102
}]
104103
mp = {
105104
'VIRT_PROTOCOL': virt_protocol,
@@ -123,30 +122,29 @@ def clear_domains(self, virt_type, inst_prefix):
123122
if not virt_protocol:
124123
LOG.warn("Could not clear out libvirt domains, no known protocol for virt type: %s", colorizer.quote(virt_type))
125124
return
126-
with sh.Rooted(True):
127-
LOG.info("Attempting to clear out leftover libvirt domains using protocol: %s", colorizer.quote(virt_protocol))
128-
try:
129-
self.restart_service()
130-
self.wait_active()
131-
except (excp.StartException, IOError) as e:
132-
LOG.warn("Could not restart the libvirt daemon due to: %s", e)
133-
return
125+
LOG.info("Attempting to clear out leftover libvirt domains using protocol: %s", colorizer.quote(virt_protocol))
126+
try:
127+
self.restart_service()
128+
self.wait_active()
129+
except (excp.StartException, IOError) as e:
130+
LOG.warn("Could not restart the libvirt daemon due to: %s", e)
131+
return
132+
try:
133+
conn = libvirt.open(virt_protocol)
134+
except libvirt.libvirtError as e:
135+
LOG.warn("Could not connect to libvirt using protocol %s due to: %s", colorizer.quote(virt_protocol), e)
136+
return
137+
with contextlib.closing(conn) as ch:
134138
try:
135-
conn = libvirt.open(virt_protocol)
136-
except libvirt.libvirtError as e:
137-
LOG.warn("Could not connect to libvirt using protocol %s due to: %s", colorizer.quote(virt_protocol), e)
138-
return
139-
with contextlib.closing(conn) as ch:
140-
try:
141-
defined_domains = ch.listDefinedDomains()
142-
kill_domains = list()
143-
for domain in defined_domains:
144-
if domain.startswith(inst_prefix):
145-
kill_domains.append(domain)
146-
if kill_domains:
147-
utils.log_iterable(kill_domains, logger=LOG,
148-
header="Found %s old domains to destroy" % (len(kill_domains)))
149-
for domain in sorted(kill_domains):
150-
self._destroy_domain(libvirt, ch, domain)
151-
except libvirt.libvirtError, e:
152-
LOG.warn("Could not clear out libvirt domains due to: %s", e)
139+
defined_domains = ch.listDefinedDomains()
140+
kill_domains = list()
141+
for domain in defined_domains:
142+
if domain.startswith(inst_prefix):
143+
kill_domains.append(domain)
144+
if kill_domains:
145+
utils.log_iterable(kill_domains, logger=LOG,
146+
header="Found %s old domains to destroy" % (len(kill_domains)))
147+
for domain in sorted(kill_domains):
148+
self._destroy_domain(libvirt, ch, domain)
149+
except libvirt.libvirtError, e:
150+
LOG.warn("Could not clear out libvirt domains due to: %s", e)

anvil/components/horizon.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,10 @@ def _setup_logs(self, clear=False):
8282
utils.log_iterable(log_fns, logger=LOG,
8383
header="Adjusting %s log files" % (len(log_fns)))
8484
for fn in log_fns:
85-
with sh.Rooted(True):
86-
if clear:
87-
sh.unlink(fn, True)
88-
sh.touch_file(fn, die_if_there=False, tracewriter=self.tracewriter)
89-
sh.chmod(fn, 0666)
85+
if clear:
86+
sh.unlink(fn, True)
87+
sh.touch_file(fn, die_if_there=False, tracewriter=self.tracewriter)
88+
sh.chmod(fn, 0666)
9089
return len(log_fns)
9190

9291
def _configure_files(self):
@@ -137,7 +136,7 @@ def _run_action(self, action, check_exit_code=True):
137136
cmd = self.distro.get_command('apache', action)
138137
if not cmd:
139138
raise NotImplementedError("No distro command provided to perform action %r" % (action))
140-
return sh.execute(*cmd, run_as_root=True, check_exit_code=check_exit_code)
139+
return sh.execute(cmd, check_exit_code=check_exit_code)
141140

142141
def restart(self):
143142
self._run_action('restart')

anvil/components/keystone.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def post_install(self):
6363
def _sync_db(self):
6464
LOG.info("Syncing keystone to database: %s", colorizer.quote(self.configurator.DB_NAME))
6565
sync_cmd = MANAGE_CMD + ['db_sync']
66-
cmds = [{'cmd': sync_cmd, 'run_as_root': True}]
66+
cmds = [{'cmd': sync_cmd}]
6767
utils.execute_template(*cmds, cwd=self.bin_dir, params=self.config_params(None))
6868

6969
@property
@@ -86,9 +86,9 @@ def _setup_pki(self):
8686
LOG.info("Setting up keystone's pki support.")
8787
for value in kconf.PKI_FILES.values():
8888
sh.mkdirslist(sh.dirname(sh.joinpths(self.configurator.link_dir, value)),
89-
tracewriter=self.tracewriter, adjust_suids=True)
89+
tracewriter=self.tracewriter)
9090
pki_cmd = MANAGE_CMD + ['pki_setup']
91-
cmds = [{'cmd': pki_cmd, 'run_as_root': True}]
91+
cmds = [{'cmd': pki_cmd}]
9292
utils.execute_template(*cmds, cwd=self.bin_dir, params=self.config_params(None))
9393

9494
def warm_configs(self):

anvil/components/nova.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,25 @@
3535

3636
# This makes the database be in sync with nova
3737
DB_SYNC_CMD = [
38-
{'cmd': ['$BIN_DIR/nova-manage', '--config-file', '$CFG_FILE', 'db', 'sync'], 'run_as_root': True},
38+
{'cmd': ['$BIN_DIR/nova-manage', '--config-file', '$CFG_FILE', 'db', 'sync']},
3939
]
4040

4141
# Used to create a fixed network when initializating nova
4242
FIXED_NET_CMDS = [
4343
{
4444
'cmd': ['$BIN_DIR/nova-manage', '--config-file', '$CFG_FILE',
4545
'network', 'create', 'private', '$FIXED_RANGE', '1', '$FIXED_NETWORK_SIZE'],
46-
'run_as_root': True,
4746
},
4847
]
4948

5049
# Used to create a floating network + test floating pool
5150
FLOATING_NET_CMDS = [
5251
{
5352
'cmd': ['$BIN_DIR/nova-manage', '--config-file', '$CFG_FILE', 'floating', 'create', '$FLOATING_RANGE'],
54-
'run_as_root': True,
5553
},
5654
{
5755
'cmd': ['$BIN_DIR/nova-manage', '--config-file', '$CFG_FILE',
5856
'floating', 'create', '--ip_range=$TEST_FLOATING_RANGE', '--pool=$TEST_FLOATING_POOL'],
59-
'run_as_root': True,
6057
},
6158
]
6259

anvil/components/quantum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def post_install(self):
4343

4444
def _sync_db(self):
4545
LOG.info("Syncing quantum to database: %s", colorizer.quote(self.configurator.DB_NAME))
46-
#cmds = [{"cmd": SYNC_DB_CMD, "run_as_root": True}]
46+
#cmds = [{"cmd": SYNC_DB_CMD}]
4747
#utils.execute_template(*cmds, cwd=self.bin_dir,
4848
# params=self.config_params(None))
4949

anvil/components/rabbit.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def pre_uninstall(self):
4343
self.runtime.start()
4444
self.runtime.wait_active()
4545
cmd = self.distro.get_command('rabbit-mq', 'change_password') + [RESET_BASE_PW]
46-
sh.execute(*cmd, run_as_root=True)
46+
sh.execute(cmd)
4747
LOG.info("Restarting so that your rabbit-mq password is reflected.")
4848
self.runtime.restart()
4949
self.runtime.wait_active()
@@ -67,7 +67,7 @@ def _setup_pw(self):
6767
self.runtime.wait_active()
6868
cmd = list(self.distro.get_command('rabbit-mq', 'change_password'))
6969
cmd += [user_id, rhelper.get_shared_passwords(self)['pw']]
70-
sh.execute(*cmd, run_as_root=True)
70+
sh.execute(cmd)
7171
LOG.info("Restarting so that your rabbit-mq password is reflected.")
7272
self.runtime.restart()
7373
self.runtime.wait_active()
@@ -123,7 +123,7 @@ def _run_action(self, action, check_exit_code=True):
123123
# RHEL seems to have this bug also...
124124
with TemporaryFile() as s_fh:
125125
with TemporaryFile() as e_fh:
126-
sh.execute(*cmd, run_as_root=True,
126+
sh.execute(cmd,
127127
stdout_fh=s_fh, stderr_fh=e_fh,
128128
check_exit_code=check_exit_code)
129129
# Read from the file handles instead of the typical output...

0 commit comments

Comments
 (0)