【问题标题】:How to inject bash command into inline-python?如何将 bash 命令注入 inline-python?
【发布时间】:2021-06-30 14:47:52
【问题描述】:

我目前正在编写一个dockerfile,其中项目的代码行数将通过cloc进行计数,并发送到服务器。服务器提供 RESTful API。我想从这个 API 获取一个 Data-Transfer-Object,对其进行修改并将其发送回同一个 API 以对其进行更新。 由于跑步者不会记住超过一行的变量,因此我(可能)必须将所有内容都放在一行中(静态 API 除外):

ENV API=http://example-url.com/api/datapoints/

到目前为止,我的 curl 命令是这样的:

RUN curl 
    -d (curl -s ${API} | python3 -c "import sys, json; 
                                     newDatapointDTO=json.load(sys.stdin); 
                                     newDatapointDTO['metric']="`cloc ./src/ --json`"; 
                                     print(newDatapointDTO)") 
    -H "Content-Type: application/json" 
    -X PUT ${API}

这里的问题是跑步者不喜欢中断python命令以便从bash中设置变量。那么我如何将cloc ./src/ --json然后插入Python?

我也觉得这个命令有点太复杂了——应该有更好的解决方案...

【问题讨论】:

  • 顺便说一句,使用命令替换将值注入 Python 代码是一个真的坏主意。您需要传入的任何参数都应使用sys.argvos.environ——这些方法不会冒shell 注入攻击的风险。
  • 另外,在开始替换命令之前不要关闭双引号;除非您希望对其结果进行字符串拆分和通配,否则应引用该替换。
  • 另外,您确定您的原始代码确实有效吗?我期望您缩进 Python 的方式会导致 IndentationError
  • 我的原始代码是第一次构建它,这是我在不知道 dockerfile 语法的情况下能想到的最佳方法。

标签: python bash rest curl dockerfile


【解决方案1】:

使用 jq -Rs . <<'EOF' 将您的命令转换为 JSON,粘贴您的命令,然后 EOF 给我们:

RUN ["bash", "-c", "curl \n    -d (curl -s ${API} | python3 -c \"import sys, json; \n                                     newDatapointDTO=json.load(sys.stdin); \n                                     newDatapointDTO['metric']=\"`cloc ./src/ --json`\"; \n                                     print(newDatapointDTO)\") \n    -H \"Content-Type: application/json\" \n    -X PUT ${API}\n"]

去掉多余的空格并修正引用使得:

RUN ["bash", "-c", "curl -d (curl -s ${API} | python3 -c \"import sys, json;\nnewDatapointDTO=json.load(sys.stdin);\nnewDatapointDTO['metric']=$(cloc ./src/ --json);print(newDatapointDTO)\") -H \"Content-Type: application/json\" -X PUT ${API}"]

但是,由于该代码使用 shell 注入将数据插入 Python,因此它仍然是一个非常糟糕的主意。你的 Python 代码的更健全的版本可能看起来像:

import sys, json, subprocess
newDatapointDTO=json.load(sys.stdin)
newDatapointDTO['metric'] = subprocess.run(['cloc', './src/', '--json'], check=True, stdout=subprocess.PIPE).stdout
print(newDatapointDTO)

...因此将其包装在 shell 命令中可能如下所示:

pythonScript="import sys, json, subprocess
newDatapointDTO=json.load(sys.stdin)
newDatapointDTO['metric'] = subprocess.run(['cloc', './src/', '--json'], check=True, stdout=subprocess.PIPE).stdout
print(newDatapointDTO)"

curl -d "$(curl -s "$API" | python -c "$pythonScript")" \
     -H "Content-Type: application/json" \
     -X PUT "$API"

...所以,生成一个命令行的 JSON 编码,调用如下所示:

jq -Rs . <<'EOF'
pythonScript="import sys, json, subprocess
newDatapointDTO=json.load(sys.stdin)
newDatapointDTO['metric'] = subprocess.run(['cloc', './src/', '--json'], check=True, stdout=subprocess.PIPE).stdout
print(newDatapointDTO)"

curl -d "$(curl -s "$API" | python -c "$pythonScript")" \
     -H "Content-Type: application/json" \
     -X PUT "$API"
EOF

...这给了我们输出:

"pythonScript=\"import sys, json, subprocess\nnewDatapointDTO=json.load(sys.stdin)\nnewDatapointDTO['metric'] = subprocess.run(['cloc', './src/', '--json'], check=True, stdout=subprocess.PIPE).stdout\nprint(newDatapointDTO)\"\n\ncurl -d \"$(curl -s \"$API\" | python -c \"$pythonScript\")\" \\\n     -H \"Content-Type: application/json\" \\\n     -X PUT \"$API\"\n"

...所以我们知道您可以在 Dockerfile 中添加以下内容:

RUN ["bash", "-c", "pythonScript=\"import sys, json, subprocess\nnewDatapointDTO=json.load(sys.stdin)\nnewDatapointDTO['metric'] = subprocess.run(['cloc', './src/', '--json'], check=True, stdout=subprocess.PIPE).stdout\nprint(newDatapointDTO)\"\n\ncurl -d \"$(curl -s \"$API\" | python -c \"$pythonScript\")\" \\\n     -H \"Content-Type: application/json\" \\\n     -X PUT \"$API\"\n"]

【讨论】:

  • 哇,这很努力 :D 非常感谢你,我还不能检查它是否给出了正确的结果,但它已经通过了管道,有什么好处!一旦我知道更多,我会尽快告诉你。除了可读性之外,额外而不是直接在命令中编写 Python 脚本有什么好处吗?
  • “可读性”就足够了。 (我首先自己编写了 Python 脚本,根本没有尝试进行任何 shell 引用;然后运行 ​​pythonScript=$(cat &lt;&lt;'EOF',将其粘贴进去,然后在单独的行中添加 EOF 然后 ) 进行初始分配;然后运行declare -p pythonScript 以将引用到 eval 的版本打印回自身,这就是我生成答案的代码的方式——该练习的重点是不需要手动编写正确引用的代码;让机器这样做可以减少出错的可能性)。
猜你喜欢
  • 1970-01-01
  • 2022-08-21
  • 2011-12-19
  • 2023-04-10
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
相关资源
最近更新 更多