-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[sonic-config-engine] Replace os.system, replace yaml.load, remove subprocess with shell=True #12533
Conversation
Signed-off-by: maipbui <maibui@microsoft.com>
@@ -47,7 +46,7 @@ def __init__(self, path=YANG_MODELS_DIR): | |||
self.yang_parser = sonic_yang.SonicYang(path) | |||
self.yang_parser.loadYangModel() | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.script_file = [PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] | |
self.script_file = [PYTHON_INTERPRETTER, os.path.join(self.test_dir, '..', 'sonic-cfggen')] | |
``` #Closed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All are fixed.
args, unknown = parser.parse_known_args(shlex.split(argument)) | ||
parser.add_argument("-o", "--output-file", help="Output file", nargs='?', const=None) | ||
args, unknown = parser.parse_known_args(argument) | ||
print(args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -62,22 +61,29 @@ def validate(self, argument): | |||
parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None) | |||
parser.add_argument("-S", "--hwsku-config", help="hwsku config file, used with -p and -m or -k", nargs='?', const=None) | |||
parser.add_argument("-j", "--json", help="additional json file input, used with -p, -S and -m or -k", nargs='?', const=None) | |||
args, unknown = parser.parse_known_args(shlex.split(argument)) | |||
parser.add_argument("-o", "--output-file", help="Output file", nargs='?', const=None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because there're some commands that have output redirection.
Original command:
argument = '-m ' + self.t0_minigraph_nomgmt + ' -p ' + self.t0_port_config_tiny + ' -j ' + self.ztp + ' -j ' + self.port_data + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + '> ' + self.output_file |
Changed command
argument = ['-m', self.t0_minigraph_nomgmt, '-p', self.t0_port_config_tiny, '-j', self.ztp, '-j', self.port_data, '-a', '{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}', '-t', interfaces_template, '-o', self.output_file] |
Implementation of new behavior:
https://github.com/sonic-net/sonic-buildimage/blob/ce3e0759543cd00a5a515b31ffb3e87de48c2e76/src/sonic-config-engine/tests/test_j2files.py#L46-#L59
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer following subprocess functions, adding stdout=None, stderr=None
to this function parameter list.
@@ -16,7 +16,7 @@ class TestCfgGen(TestCase): | |||
def setUp(self): | |||
self.yang = utils.YangWrapper() | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -52,13 +52,12 @@ def tearDown(self): | |||
pass | |||
|
|||
def run_script(self, argument, check_stderr=False, verbose=False): | |||
print('\n Running sonic-cfggen ' + argument) | |||
print('\n Running sonic-cfggen ', argument) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but argument
variable is a list, cannot be concatenated with string in the print statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to shlex.join
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice it is not available in python 3.7. Then +
is good enough in test code.
@@ -21,17 +21,17 @@ class TestCfgGenPlatformJson(TestCase): | |||
|
|||
def setUp(self): | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -10,18 +10,18 @@ class TestCfgGenT2ChassisFe(TestCase): | |||
|
|||
def setUp(self): | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.sample_graph_t2_chassis_fe = os.path.join(self.test_dir, 't2-chassis-fe-graph.xml') | ||
self.sample_graph_t2_chassis_fe_vni = os.path.join(self.test_dir, 't2-chassis-fe-graph-vni.xml') | ||
self.sample_graph_t2_chassis_fe_pc = os.path.join(self.test_dir, 't2-chassis-fe-graph-pc.xml') | ||
self.t2_chassis_fe_port_config = os.path.join(self.test_dir, 't2-chassis-fe-port-config.ini') | ||
|
||
def run_script(self, argument, check_stderr=False): | ||
print('\n Running sonic-cfggen ' + argument) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -11,7 +11,7 @@ | |||
class TestJ2FilesT2ChassisFe(TestCase): | |||
def setUp(self): | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -25,23 +25,32 @@ def tearDown(self): | |||
pass | |||
|
|||
def run_script(self, argument): | |||
print('CMD: sonic-cfggen ' + argument) | |||
output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) | |||
print('CMD: sonic-cfggen ', argument) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -17,7 +17,7 @@ class TestCfgGenCaseInsensitive(TestCase): | |||
def setUp(self): | |||
self.yang = utils.YangWrapper() | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -27,13 +27,13 @@ def setUp(self): | |||
self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') | |||
|
|||
def run_script(self, argument, check_stderr=False): | |||
print('\n Running sonic-cfggen ' + argument) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -23,7 +23,7 @@ def setUp(self): | |||
self.yang = utils.YangWrapper() | |||
self.test_dir = os.path.dirname(os.path.realpath(__file__)) | |||
self.test_data_dir = os.path.join(self.test_dir, 'multi_npu_data') | |||
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') | |||
self.script_file = [utils.PYTHON_INTERPRETTER] + [os.path.join(self.test_dir, '..', 'sonic-cfggen')] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -34,16 +34,24 @@ def setUp(self): | |||
os.environ["CFGGEN_UNIT_TESTING"] = "2" | |||
|
|||
def run_script(self, argument, check_stderr=False): | |||
print('\n Running sonic-cfggen ' + argument) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed-off-by: maipbui <maibui@microsoft.com>
Signed-off-by: maipbui <maibui@microsoft.com>
write_output = False | ||
if '-o' in argument: | ||
write_output = True | ||
output_file = argument[-1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How to guarantee '-o' is the last argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed to different solution.
os.system(echo_cmd) | ||
subprocess.call(['sudo', 'mkdir', '/host']) | ||
subprocess.call(['sudo', 'touch', '/host/machine.conf']) | ||
getstatusoutput_noshell_pipe(echo_cmd1, echo_cmd2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain these commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check this PR #12065
|
||
return file_exist, dir_exist | ||
|
||
def remove_machine_conf(self, file_exist, dir_exist): | ||
if not file_exist: | ||
os.system('sudo rm -f /host/machine.conf') | ||
subprocess.call(['sudo', 'rm', '-f', '/host/machine.conf']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's no user input in 'sudo rm -f /host/machine.conf', why is it a risk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better for extra security when using subprocess and with array of strings. https://semgrep.dev/docs/cheat-sheets/python-command-injection/#1c-using-os-module-to-execute-commands
Signed-off-by: maipbui <maibui@microsoft.com>
….load, remove subprocess with shell=True (sonic-net#12533)" (sonic-net#12616)" This reverts commit 661c467.
…ubprocess with shell=True (#12607) Signed-off-by: maipbui <maibui@microsoft.com> #### Why I did it Missing import statement in PR #12533 #### How I did it Revert [PR 12646](#12616) Add import statement 1. https://github.com/sonic-net/sonic-buildimage/blob/31f7afa92e8d1e353ef2f3b004711dd18c0d94f6/src/sonic-config-engine/tests/test_j2files_t2_chassis_fe.py#L8 2. https://github.com/sonic-net/sonic-buildimage/blob/31f7afa92e8d1e353ef2f3b004711dd18c0d94f6/src/sonic-config-engine/tests/test_j2files.py#L8 3. https://github.com/sonic-net/sonic-buildimage/blob/31f7afa92e8d1e353ef2f3b004711dd18c0d94f6/src/sonic-config-engine/tests/test_multinpu_cfggen.py#L11 #### How to verify it Pass UT
Signed-off-by: maipbui maibui@microsoft.com
Why I did it
subprocess
is used withshell=True
, which is very dangerous for shell injection.os
- not secure against maliciously constructed input and dangerous if used to evaluate dynamic contentyaml.load
can create arbitrary Python objectsHow I did it
Replace
os
bysubprocess
, removeshell=True
Use
yaml.safe_load()
How to verify it
Pass UT
Which release branch to backport (provide reason below if selected)
Description for the changelog
Ensure to add label/tag for the feature raised. example - PR#2174 under sonic-utilities repo. where, Generic Config and Update feature has been labelled as GCU.
Link to config_db schema for YANG module changes
A picture of a cute animal (not mandatory but encouraged)