Skip to content

Commit

Permalink
Enhancements to allow custom umask usage while executing plugins (son…
Browse files Browse the repository at this point in the history
…ic-net#42)

 - Use default umask value of 022 to execute ztp plugins

 - User can provide a custom umask octal value string as part of plugin data if a specific umask is required. { "plugin" : { "url" : "http://10.1.1.1/plugins/my-plugin", "umask" : "177" } }

 - Firmware plugin has been modified to always use 022 umask when installing sonic image

 - Added unit test cases to test user specified umask value
  • Loading branch information
rajendra-dendukuri authored Feb 14, 2024
1 parent 739470d commit 56cebae
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 5 deletions.
6 changes: 3 additions & 3 deletions src/usr/lib/python3/dist-packages/ztp/ZTPLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def getTimestamp():
## Global variable to keep track of the pid or process created by runCommand()
runcmd_pids = []

def runCommand(cmd, capture_stdout=True, use_shell=False):
def runCommand(cmd, capture_stdout=True, use_shell=False, umask=-1):
'''!
Execute a given command
Expand Down Expand Up @@ -95,7 +95,7 @@ def runCommand(cmd, capture_stdout=True, use_shell=False):
else:
shcmd = cmd
if capture_stdout is True:
proc = subprocess.Popen(shcmd, shell=use_shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
proc = subprocess.Popen(shcmd, shell=use_shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, umask=umask)
pid = proc.pid
runcmd_pids.append(pid)
output_stdout, output_stderr = proc.communicate()
Expand All @@ -109,7 +109,7 @@ def runCommand(cmd, capture_stdout=True, use_shell=False):
list_stderr.append(str(l.decode()))
return (proc.returncode, list_stdout, list_stderr)
else:
proc = subprocess.Popen(shcmd, shell=use_shell)
proc = subprocess.Popen(shcmd, shell=use_shell, umask=umask)
pid = proc.pid
runcmd_pids.append(pid)
proc.communicate()
Expand Down
1 change: 1 addition & 0 deletions src/usr/lib/python3/dist-packages/ztp/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"section-input-file" : "input.json", \
"sighandler-wait-interval" : 60, \
"test-mode" : False, \
"umask" : "022", \
"ztp-activity" : '/var/run/ztp/activity', \
"ztp-cfg-dir" : "/host/ztp", \
"ztp-json" : "/host/ztp/ztp_data.json", \
Expand Down
2 changes: 1 addition & 1 deletion src/usr/lib/ztp/plugins/firmware
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ class Firmware:
# Execute sonic-installer command
logger.info('firmware: Installing firmware image located at \'%s\'.' % self.__dest_file)
updateActivity('firmware: Installing firmware image located at \'%s\'.' % self.__dest_file)
rc = runCommand(cmd, capture_stdout=False)
rc = runCommand(cmd, capture_stdout=False, umask=0o022)
if rc != 0:
self.__bailout('Error (%d) encountered while processing command : %s' % (cmd))

Expand Down
9 changes: 8 additions & 1 deletion src/usr/lib/ztp/ztp-engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,13 @@ def __processConfigSections(self):
# Determine if shell has to be used to execute plugin
_shell = getField(plugin_data, 'shell', bool, False)

# Determine if user specified umask has to be used to execute plugin
try:
_umask = int(getField(plugin_data, 'umask', str, getCfg("umask")), 8)
except Exception as e:
logger.error('Exception[%s] encountered while reading umask to execute the plugin for %s. Using default value -1.' % (str(e), sec))
_umask = -1

# Construct the full plugin command string along with arguments
plugin_cmd = plugin
if plugin_args is not None:
Expand All @@ -506,7 +513,7 @@ def __processConfigSections(self):
# A plugin has been resolved and its input configuration section data as well
logger.debug('Executing plugin %s.' % (plugin_cmd))
# Execute identified plugin
rc = runCommand(plugin_cmd, capture_stdout=False, use_shell=_shell)
rc = runCommand(plugin_cmd, capture_stdout=False, use_shell=_shell, umask=_umask)

logger.debug('Plugin %s exit code = %d.' % (plugin_cmd, rc))
# Compare plugin exit code
Expand Down
8 changes: 8 additions & 0 deletions tests/test_ZTPLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ def test_cmd(self, tmpdir):
assert((cmd_stdout1 == cmd_stdout2) and (cmd_stdout2 == cmd_stdout3) and (cmd_stdout3 == cmd_stdout4))
assert((cmd_stderr1 == cmd_stderr2) and (cmd_stderr2 == cmd_stderr3) and (cmd_stderr3 == cmd_stderr4))

(rc5, cmd_stdout5, cmd_stderr5) = runCommand(['touch', '/tmp/test_file_644'], use_shell=True, umask=0o022)
st = os.stat('/tmp/test_file_644')
assert(0o644, oct(st.st_mode))
(rc6, cmd_stdout6, cmd_stderr6) = runCommand(['touch', '/tmp/test_file_600'], use_shell=True, umask=0o177)
st = os.stat('/tmp/test_file_600')
assert(0o600, oct(st.st_mode))
runCommand("rm -f /tmp/test_file_644 /tmp/test_file_600")

(rc1, cmd_stdout1, cmd_stderr1) = runCommand('ps hjk')
(rc2, cmd_stdout2, cmd_stderr2) = runCommand('ps hjk', use_shell=True)
(rc3, cmd_stdout3, cmd_stderr3) = runCommand(['ps', 'hjk'])
Expand Down
23 changes: 23 additions & 0 deletions tests/test_ztp_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ def test_ztp_json(self):
"message-file" : "/etc/ztp.results",
"fail" : false,
"status" : "DISABLED"
},
"0005-test-plugin": {
"plugin" : {
"name" : "test-plugin",
"umask" : "177"
},
"message" : "umask-check",
"message-file" : "/tmp/test_plugin_umask_600"
},
"0006-test-plugin": {
"plugin" : {
"name" : "test-plugin",
"umask" : "177"
},
"message" : "umask-check",
"message-file" : "/tmp/test_plugin_umask_644"
}
}
}"""
Expand Down Expand Up @@ -219,6 +235,13 @@ def test_ztp_json(self):
assert(jsonDict.get('ztp').get('0004-test-plugin').get('timestamp') != None)
assert(jsonDict.get('ztp').get('0004-test-plugin').get('exit-code') == 0)

st = os.stat("/tmp/test_plugin_umask_600")
assert(0o600, oct(st.st_mode))

st = os.stat("/tmp/test_plugin_umask_644")
assert(0o644, oct(st.st_mode))
runCommand("rm -f /tmp/test_plugin_umask_600 /tmp/test_plugin_umask_644")

old_timestamp = jsonDict.get('ztp').get('timestamp')
runCommand(COVERAGE + ZTP_ENGINE_CMD)
runCommand(COVERAGE + ZTP_CMD + ' status -v')
Expand Down

0 comments on commit 56cebae

Please sign in to comment.