bash - saltstack - 传递变量包含单引号、双引号、空格……到 cmd.script?

标签 bash escaping yaml salt-stack jinja2

我有一个使用 logger 来模拟一些“虚假”登录的脚本:

#!/bin/bash

{%- set maxretry = salt['pillar.get']('fail2ban:maxretry', 3) %}

tag="$1"
message="$2"

logger -p auth.info "The {{ maxretry + 1 }} \"$tag\" below lines are generated by logger to test Fail2ban"

for i in $(seq {{ maxretry + 1 }}); do
    logger -p auth.warning -t "$tag" "$message"
done

在宏中调用:

fake_{{ formula }}_login:
  cmd:
    - script
    - source: salt://fail2ban/fake_login.jinja2
    - template: jinja
    - args: "{{ tag|default(formula) }} '{{ message }}'"
    - require:
      - sls: bash
      - sls: fail2ban

问题是 {{ message }} 可以包含单引号/双引号、空格、方括号... 根据 cmd.script 文档,要传递包含空格的字符串,我们必须将其加双引号。 但是如果我有这样的东西:

{{ fail2ban_regex_test('mysql', tag='mysqld', message="150114  3:40:50 [Warning] Access denied for user 'root'@'5.6.7.8' (using password: YES)") }}

它将记录到系统日志中,用户/主机周围没有单引号,只是:

mysqld: 150114  3:40:50 [Warning] Access denied for user root@5.6.7.8 (using password: YES)

make fail2ban 无法识别,因为它与过滤器正则表达式不匹配。

我可以把单引号改成双引号,用反斜杠转义:

fake_{{ formula }}_login:
  cmd:
    - script
    - source: salt://fail2ban/fake_login.jinja2
    - template:
jinja
    - args: "{{ tag|default(formula) }} \"{{ message|safe }}\""

    - require:
      - sls: bash
      - sls: fail2ban

当消息只包含单引号时,它处理上述情况。

但是如果它包含双引号:

{{ fail2ban_regex_test('postfix', tag='postfix/smtpd[20228]', message="NOQUEUE: reject: RCPT from sender.com["5.6.7.8"]: 554 5.7.1 <us...@example.com>: Recipient address rejected: Access denied; from=<us...@sender.com> to=<us...@example.com> proto=ESMTP helo=<mg01d1.sender.com>") }}

我遇到了这个错误:

local:
    Data failed to compile:
----------
    Rendering SLS "base:postfix.test" failed: Jinja syntax error: expected token ',', got 'float'; line 29


---
[...]
- sls: openldap
- sls: openldap.diamond
- sls: openldap.nrpe
{%- endcall %}


{{ fail2ban_regex_test('postfix', tag='postfix/smtpd[20228]', message="NOQUEUE: reject: RCPT from sender.com["5.6.7.8"]: 554 5.7.1 <us...@example.com>: Recipie
nt address rejected: Access denied; from=<us...@sender.com> to=<us...@example.com> proto=ESMTP helo=<mg01d1.sender.com>") }}    <======================

如果我试图用反斜杠转义双引号:

... message="NOQUEUE: reject: RCPT from sender.com[\"5.6.7.8\"] ...

然后我得到另一个错误:

local:
    Data failed to compile:
----------
    Rendering SLS postfix.test failed, render error: while parsing a block mapping
  in "<unicode string>", line 84, column 7:
        - args: "postfix/smtpd[20228] \"NO ...
          ^
expected <block end>, but found '<scalar>'
  in "<unicode string>", line 84, column 76:
     ... : reject: RCPT from sender.com["5.6.7.8"]: 554 5.7.1 <user@examp ...

如何处理这两种情况?

最佳答案

saltstack 使用一些 custom filters 扩展了 jinja 内置过滤器:

  • yaml_dquote:将字符串序列化为正确转义的 YAML 双引号字符串。
  • yaml_encode:将单个对象序列化为 YAML 标量,并进行任何必要的转义特殊字符处理。

类似于:

{%- set foo = 7.7 %}
{%- set bar = none %}
{%- set baz = true %}
{%- set zap = 'The word of the day is "salty".' %}
{%- set zip = '"The quick brown fox . . ."' %}

foo: {{ foo|yaml_encode }}
bar: {{ bar|yaml_encode }}
baz: {{ baz|yaml_encode }}
zap: {{ zap|yaml_encode }}
zip: {{ zip|yaml_dquote }}

给你:

foo: 7.7
bar: null
baz: true
zap: "The word of the day is \"salty\"."
zip: "\"The quick brown fox . . .\""

对于任意字符串,即使 {{ var|yaml_encode|yaml_decode }} 也可能不起作用。最好先对字符串进行编码,然后再用脚本对其进行解码。

关于bash - saltstack - 传递变量包含单引号、双引号、空格……到 cmd.script?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29135939/

相关文章:

batch-file - 检查字符串是否被引用并向字符串添加引号的问题

postgresql - 使用 ASCII 31 字段分隔符作为 Postgresql COPY 分隔符

无论路径如何,Azure 管道触发器都包括

image - 使用 netcat 提供包含图像的 HTTP 响应

bash - 如何通过在 ubuntu 中包含 "cd"命令来运行 shell 脚本?

powershell - 将带引号的参数从批处理文件传递给 `powershell start` - 按需 self 提升

ruby-on-rails - 如何在 Rails 中构造 i18n yaml 文件?

php - SQL从脏数据集创建新数据库

linux - 创建一个脚本,该脚本将从用户名的 .txt 文件创建用户帐户(使用 useradd)

php - Symfony 找不到 "GET/logout"的路由