使用 Ansible,如何在不丢失左填充的情况下将私钥写入文本文件?

With Ansible, how do I write a private key to a text file without losing the left padding?

换句话说,我希望将来自 Ansible 变量的内容写入配置文件中的特定“列”,并且我不希望该内容被包装。

任务:

- name: build cloud-init file
  local_action:
    module: ansible.builtin.template
    src: cloud_config.j2
    dest: ./cloud_config.yml
    mode: 0640
  tags: ['containers', 'containers:configuration']

保存在库文件中的变量:

machineuser_key: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
    ...

模板:

write_files:
{# ssh config to allow our deployment user to fetch the Ansible repo #}
{# See https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users #}
- path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
  permissions: 600
  owner: {{ gcp_deploy_user }}
  content: |
    {{ machineuser_key }} 

该模板任务的输出:

write_files:
- path: /home/omegasphinx/.ssh/omegasphinx_github_rsa
  permissions: 600
  owner: omegasphinx
  content: |
    -----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
...

我知道 blockinfile 是一个推荐的模块,当有人想写一个配置文件时,我应该使用 。但是当我做这些事情的时候,它仍然包裹着ssh key的内容。 blockinfile 任务如下所示:

- name: add ssh private key to cloud-init file
  local_action:
    module: ansible.builtin.blockinfile
    path: cloud_config.yml
    mode: 0440
    insertafter: "# machineuser_ssh_block"
    block: |2
      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: |
          {{ machineuser_key }}
  tags: ['containers', 'containers:configuration']

.j2 模板如下所示:

write_files:
# machineuser_ssh_block

输出看起来像这样(完全一样):

write_files:
 - path: /home/omegasphinx/.ssh/omegasphinx_github_rsa
  permissions: 600
  owner: omegasphinx
  content: |
    -----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
...

我尝试过的其他事情:

  {%+ if machineuser_key is defined %}
    {{ machineuser_key }} 
  {% endif %}

我对 Jinja2 中空格的理解:

给你一些关于我期待发生的事情的背景。 Jinja 文档的“Whitespace Control”部分指出“如果存在单个尾随换行符,则将被删除”,但“其他空格(空格、制表符、换行符等)将原封不动地返回。”在我的例子中,我有“其他空白”:变量 machineuser_key 每一行左侧的空格。但显然我错过了一些东西。

据我从你的问题中可以看出,干扰你结果的不是 jinja 空格控制,而是 machineuser_key 本身嵌入了换行符;许多 helm 图表都有同样的问题,这使您可以利用相同的解决方法:

  • 利用 YAML 是 JSON
  • 的超集这一事实
  • 使用 indent filter 让您和 YAML 块在同一页面上

JSON 作为 YAML 方法

      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: {{ machineuser_key | to_json }}

导致

        owner: gcpawesomeuser
        content: "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nETC ETC ETC\n"

使用缩进过滤器

      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: |
          {{ machineuser_key | indent(2) }}
# with the (2) matching the number of spaces under "content" where the mustaches start

生产:

        owner: gcpawesomeuser
        content: |
          -----BEGIN OPENSSH PRIVATE KEY-----
          b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
          ETC ETC ETC