Python Ansible和jinja-将双引号转义的JSON字符串发送到AWS

Python Ansible和jinja-将双引号转义的JSON字符串发送到AWS,python,ansible,jinja2,Python,Ansible,Jinja2,我们需要为nodeJS产品的AWS机密提供一个双引号转义JSON字符串。单引号内双引号格式不适用于应用程序。结构化数据采用dict list dict格式。例如: { "data": "[{\"URL\": \"beta.test.net\", \"token\": \"beta-token\"}, {\"URL\": \"beta-prod.test.net\", \"token\": \"beta-prod-token\"}]" } token_list: "{{ (token_l

我们需要为nodeJS产品的AWS机密提供一个双引号转义JSON字符串。单引号内双引号格式不适用于应用程序。结构化数据采用dict list dict格式。例如:

{
  "data": "[{\"URL\": \"beta.test.net\", \"token\": \"beta-token\"}, {\"URL\": \"beta-prod.test.net\", \"token\": \"beta-prod-token\"}]"
}
  token_list: "{{ (token_list | default([]) + [_update]) | to_json }}"
我尝试了许多过滤器,让ansible和jinja获取JSON变量并将其转换为所需格式的字符串,但结果总是不太正确to_json |字符串给出以下结果:

{
  "data": "[{'URL': 'beta.test.net', 'token': 'beta-token'}, {'token': 'test-token', 'URL': 'beta-prod.test.net'}]"
}
当我尝试使用replace或regexreplace时,似乎即使使用一个保护字符,我最终也会遇到python解析错误。这里有一个例子,用grave的重音“escape”替换

TASK [Update secret in AWS] ***************************************************************************************************
task path: path:27
The full traceback is:
Traceback (most recent call last):
  File "/home/.local/lib/python3.5/site-packages/ansible/executor/task_executor.py", line 146, in run
    res = self._execute()
  File "/home/.local/lib/python3.5/site-packages/ansible/executor/task_executor.py", line 587, in _execute
    self._task.post_validate(templar=templar)
  File "/home/.local/lib/python3.5/site-packages/ansible/playbook/task.py", line 296, in post_validate
    super(Task, self).post_validate(templar)
  File "/home/.local/lib/python3.5/site-packages/ansible/playbook/base.py", line 431, in post_validate
    value = templar.template(getattr(self, name))
  File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 623, in template
    disable_lookups=disable_lookups,
  File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 578, in template
    disable_lookups=disable_lookups,
  File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 806, in do_template
    data = _escape_backslashes(data, myenv)
  File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 149, in _escape_backslashes
    for token in jinja_env.lex(d2):
  File "/home/.local/lib/python3.5/site-packages/jinja2/lexer.py", line 739, in tokeniter
    name, filename)
jinja2.exceptions.TemplateSyntaxError: unexpected char '`' at 51
  line 1
fatal: [beta-prod]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}
使用regex replace,我可以完全删除单引号并用“\”替换它,但是任何添加“\”的尝试都会失败,并出现上述解析错误

以下是调用AWS secrets的ansible代码,并尝试提供正确的格式:

    - name: Update secret in AWS
      aws_secret:
        name: '{{ aws_secret_name }}'
        state: present
        secret_type: 'string'
 #       secret: "{{ token_list_update | to_json | replace(\"'\",\"\") | string }}"
        secret: '{{ token_list_update | to_json | string }}'
   #     secret: ' {"data": "{{ token_list | to_json | regex_replace(`"`,`\\"`) }}"}'
任何帮助都将不胜感激。我得到了一个想法,我需要编写自己的过滤器来处理这个问题。我问过应用程序是否会接受单引号内双引号JSON字符串,但团队表示这是不可接受的。格式必须是双引号转义JSON字符串

最终编辑:

经过几天的工作后,我们找到了这个问题。在每个步骤中,您都需要转换正确的类型以保留JSON格式。在执行更新时,每个列表元素都需要过滤为_JSON。示例:

{
  "data": "[{\"URL\": \"beta.test.net\", \"token\": \"beta-token\"}, {\"URL\": \"beta-prod.test.net\", \"token\": \"beta-prod-token\"}]"
}
  token_list: "{{ (token_list | default([]) + [_update]) | to_json }}"
_update是一个辅助变量,它是JMESPath搜索

最终提交至AWS:

    - name: Update secret in AWS
      aws_secret:
        name: "{{ aws_secret_name }}"
        state: present
        secret_type: "string"
        secret: "{\"data\":{{ token_list | to_json}}}"

有点长,但这应该能满足你的需要

剧本

---
-主机:本地主机
任务:
-名称:获取字符串
shell:“python3.7打印字符串.py”
寄存器:json_字符串
-名称:AWS中的更新机密
aws_秘密:
名称:“测试/json_字符串”
国家:现在
密码类型:“字符串”
秘密:{{json_string['stdout']| string}”
打印字符串.py

导入json
数据={
“数据:”[{'URL':'beta.test.net','token':'beta-token'},{'token':'beta-prod-token','URL':'beta-prod.test.net'}]
}
打印(json.dumps(data).replace(“[{\'”,[{\'”).replace(“\':\”,“\\”:\\”).replace(“\'”,“\\”))
将产生:

{
  "data": "[{\"URL\": \"beta.test.net\", \"token\": \"beta-token\"}, {\"token\": \"beta-prod-token\", \"URL\": \"beta-prod.test.net\"}]"
}

使用本机jinja2筛选器:
tojson

我使用它的方式如下:

toto.json.j2:

{"hello" : "world"}
这将产生:

"{\"hello\" : \"world\"}"

token\u list\u update
此值是什么?如果您在不使用非JSON字符(如反勾号)的情况下发布了收到的错误,这也会很有帮助;我怀疑ansible的做法是正确的,但是如果您不习惯,将消息打包为JSON的默认标准输出回调本身可能会让您感到困惑。更进一步,您是否确定
secret:{{token_list_update | to_JSON}“
没有按您的要求执行操作?您是否签入AWS以查看该项是否按您的预期存储?
令牌列表更新
是dict列表dict本机对象。很抱歉,我没有澄清这一点。
”{{token列表更新| to _json}
在AWS中存储了不正确的值-
{data”:”[{'URL':'beta.test.net','token':'beta-token'},{'token':'test-token','URL':'beta-prod.test.net'}]“}
谢谢您的帮助,Danny!不幸的是我们无法解决问题,但是,我确实找到了一个解决方案,我现在正在更新它。我测试了它,并且它似乎可以转换成:
[警告]:值(键入dict)在字符串字段中,已转换为(类型字符串)。如果这与您期望的不一样,请引用整个值以确保它不会更改。
检查AWS中的机密。我更新了帖子,并在AWS机密管理器中放置了一张图片。请告诉我您的想法。我们的开发人员得到了相同的结果,它与您用作源的字符串有关。该格式有效,但我们的源代码是以下字符串:
{“data”:“[{\'URL\':\'beta.test.net\',\'token\':\'beta-token\',{\'URL\':\'beta-prod.test.net\',\'token\':\'beta-prod-token\'”}”
引用源代码似乎会有所不同-无论哪种方式,一旦我有了解决方案就会更新你好,我喜欢这种方法,但它会在列表周围看到新的引号,我们如何删除它这是正常的,这是一个字符串。不知道如何删除它,可能是使用子字符串过滤器