Salt stack 如何使用saltstack一次性设置随机键

Salt stack 如何使用saltstack一次性设置随机键,salt-stack,Salt Stack,我为rails安装了如下配置(简化): 所以它是从模板文件安装的 {{ role }}: secret_key_base: {{ secret_key }} db_username: {{ db_user }} db_password: {{ db_pass }} 角色和db user/pass从支柱中提取并安装在该文件中。随机生成的密钥是有意义的,例如,{{salt['random.get_str'](length=80)}。但我只想生成一次,而不是每次渲染模板时。(

我为rails安装了如下配置(简化):

所以它是从模板文件安装的

{{ role }}:
    secret_key_base: {{ secret_key }}
    db_username: {{ db_user }}
    db_password: {{ db_pass }}
角色和db user/pass从支柱中提取并安装在该文件中。随机生成的密钥是有意义的,例如,
{{salt['random.get_str'](length=80)}
。但我只想生成一次,而不是每次渲染模板时。(更改密钥会使Cookie无效,而不是每次运行salt时都要执行的操作。)

我找到的唯一解决方案是两个阶段:我在文件中有一个
模板

{{ role }}:
    secret_key_base: ||secret_key_base||
    db_username: {{ db_user }}
    db_password: {{ db_pass }}
我在任何给定的仆从身上插入我的模板文件:

/srv/salt/rails/secrets.yml:
  cmd.run:
    # Fill in the secret key base (used for cookies).  We can't use
    # jinja2 for this, since jinja would complain about the other
    # variables that it doesn't know how to replace.  We want our
    # output to be a jinja template.
    - name: |
        cat /srv/salt/rails/secrets.yml.in | \
          sed -e 's/||secret_key_base||/{{ salt['random.get_str'](length=80) }}/;' | \
          cat > /srv/salt/rails/secrets.yml
        chmod 400 /srv/salt/rails/secrets.yml
    - creates: /srv/salt/rails/secrets.yml
    - runas: root

/var/railroad/{{host_role}}/shared/config/secrets.yml:
  file.managed:
    - source: salt://rails/secrets.yml
    - mode: 400
    - user: railroad-{{host_role}}
    - group: railroad-{{host_role}}
    - template: jinja
    - defaults:
        role: host_role
        db_username: m_u
        db_password: m_p
这是可行的,但缺点是对
secrets.yml.in
的更改不会传播到
secrets.yml
。(假设我们向机密文件添加另一个密钥。)它也感觉比必要时更笨重

有更好的办法吗

更好的方法 正如评论中所指出的,更好的方法是手工生成秘密(毕竟,它只在主机设置中完成)并将其存储在支柱中,在支柱中我们必须对每个主机说几句话

{% set fqdn = grains.get('fqdn', 'unknown-host-fqdn') %}
{% set host_role = pillar['host_credentials']
                         [grains.get('fqdn')]
                         ['role'] %}
{% set examplecom_web_app = pillar['host_credentials']
                                  [grains.get('fqdn')]
                                  ['examplecom-web-app'] %}
{% set mysql_server_host = examplecom_web_app.mysql.host %}
{% set mysql_server_database = examplecom_web_app.mysql.database %}
{% set mysql_server_role = examplecom_web_app.mysql.role %}
{% set mysql_server_spec = pillar['host_credentials']
                                 [mysql_server_host]
                                 ['mysql'] %}
{% set mongodb_server_host = examplecom_web_app.mongodb.host %}
{% set mongodb_server_spec = pillar['host_credentials']
                                   [mongodb_server_host]
                                   ['mongodb'] %}
/var/examplecom/railroad/{{host_role}}/shared/config/secrets.yml:
  file.managed:
    - source: salt://rails/secrets.yml
    - mode: 400
    - user: railroad-{{host_role}}
    - group: railroad-{{host_role}}
    - template: jinja
    - defaults:
        role: {{ host_role }}
        secret_key_base: {{ examplecom_web_app.secret_key_base }}
        mysql_hostname: {{ mysql_server_host }}
        mysql_username: {{ mysql_server_spec[mysql_server_database]
                                            [mysql_server_role]
                                            ['username'] }}
        mysql_password: {{ mysql_server_spec[mysql_server_database]
                                            [mysql_server_role]
                                            ['password'] }}
        mongodb_hostname: {{ mongodb_server_host }}
        mongodb_username: {{ mongodb_server_spec.username }}
        mongodb_password: {{ mongodb_server_spec.password }}
下面是工作代码最终的样子,对于那些可能想看到更复杂的东西的人来说是不简单的。最复杂的是我的
host\u凭证
支柱数据,它试图描述我们需要了解的关于每个主机的所有信息

{% set fqdn = grains.get('fqdn', 'unknown-host-fqdn') %}
{% set host_role = pillar['host_credentials']
                         [grains.get('fqdn')]
                         ['role'] %}
{% set examplecom_web_app = pillar['host_credentials']
                                  [grains.get('fqdn')]
                                  ['examplecom-web-app'] %}
{% set mysql_server_host = examplecom_web_app.mysql.host %}
{% set mysql_server_database = examplecom_web_app.mysql.database %}
{% set mysql_server_role = examplecom_web_app.mysql.role %}
{% set mysql_server_spec = pillar['host_credentials']
                                 [mysql_server_host]
                                 ['mysql'] %}
{% set mongodb_server_host = examplecom_web_app.mongodb.host %}
{% set mongodb_server_spec = pillar['host_credentials']
                                   [mongodb_server_host]
                                   ['mongodb'] %}
/var/examplecom/railroad/{{host_role}}/shared/config/secrets.yml:
  file.managed:
    - source: salt://rails/secrets.yml
    - mode: 400
    - user: railroad-{{host_role}}
    - group: railroad-{{host_role}}
    - template: jinja
    - defaults:
        role: {{ host_role }}
        secret_key_base: {{ examplecom_web_app.secret_key_base }}
        mysql_hostname: {{ mysql_server_host }}
        mysql_username: {{ mysql_server_spec[mysql_server_database]
                                            [mysql_server_role]
                                            ['username'] }}
        mysql_password: {{ mysql_server_spec[mysql_server_database]
                                            [mysql_server_role]
                                            ['password'] }}
        mongodb_hostname: {{ mongodb_server_host }}
        mongodb_username: {{ mongodb_server_spec.username }}
        mongodb_password: {{ mongodb_server_spec.password }}

顺便说一句,我很高兴地发现jinja2是不可知空白的,这对此类查找的可读性有很大帮助。

我理解正确吗:
-这是无盐跑步?
-在masterless节点上生成一些模板文件(一次生成一些静态部件)
-是否将
文件.managed
状态应用于以前生成的文件

假设我的理解是:

首先,如果设置正确,将被传播到另一个状态,但在您的情况下,这将很难实现,因为您已使用
cmd.run
进行模板解析(您必须添加
有状态
参数)

备注:
-你看到了吗?似乎您可以使用它来替换第一个
cmd.run
并“免费”获取文件更改检测
-至于一次性密码生成,只需使用

由于生成的密码对于给定的仆从(在您的情况下,您掌握的节点较少)不会更改,
文件.blockreplace
不会报告任何更改,除非您将更改添加到模板中

说到这里,我认为我们可以更进一步,您的状态实际上可以像这样简单(模板更改将始终传播,密钥将生成一次):


我理解正确吗:
-这是无盐跑步?
-在masterless节点上生成一些模板文件(一次生成一些静态部件)
-是否将
文件.managed
状态应用于以前生成的文件

假设我的理解是:

首先,如果设置正确,将被传播到另一个状态,但在您的情况下,这将很难实现,因为您已使用
cmd.run
进行模板解析(您必须添加
有状态
参数)

备注:
-你看到了吗?似乎您可以使用它来替换第一个
cmd.run
并“免费”获取文件更改检测
-至于一次性密码生成,只需使用

由于生成的密码对于给定的仆从(在您的情况下,您掌握的节点较少)不会更改,
文件.blockreplace
不会报告任何更改,除非您将更改添加到模板中

说到这里,我认为我们可以更进一步,您的状态实际上可以像这样简单(模板更改将始终传播,密钥将生成一次):


我建议将秘密放在一个柱子中,并在主屏幕上(手动)生成一次值。这样,您就可以避免在SLS文件中执行动态状态魔术


jma更新了他的问题,加入了一个示例解决方案。

我建议将秘密放在一个柱子中,并在主屏幕上(手动)生成一次值。这样,您就可以避免在SLS文件中执行动态状态魔术


jma更新了他的问题,加入了一个示例解决方案。

您使用的是支柱系统吗?我会简单地把秘密放在一个柱子里,然后在主机上手动生成一次。我正在使用柱子。而且。。。是的,那会更简单。好主意。谢谢。@code_onkel了解历史(并通过尝试更多的答案来避免人们的到来),您想将您的答案作为答案记录下来,我会接受它吗?您使用的是支柱系统吗?我会简单地把秘密放在一个柱子里,然后在主机上手动生成一次。我正在使用柱子。而且。。。是的,那会更简单。好主意。谢谢。@code_onkel For history(为了避免人们尝试更多的答案而来),你愿意把你的答案记为答案吗?我会接受的。是的,我想这会有用的。但请参见上文@code_onkel的评论。这甚至更容易藏在柱子里完成。这里值得一提的是,谷物并不是储存秘密的好地方。我只发现有人写过,但有几个理由不这么做。支柱是用来存储机密的。实际上,外部加密支柱或gpg_支柱是用来存储机密的,而不仅仅是支柱。但作者并没有对这样的要求说一句话,我想这是可行的。但请参见上文@code_onkel的评论。这甚至更容易藏在柱子里完成。这里值得一提的是,谷物并不是储存秘密的好地方。我只发现有人写过,但有几个理由不这么做。支柱是用来存储机密的。实际上,外部加密支柱或gpg_支柱是用来存储机密的,而不仅仅是支柱。但作者对此只字未提
/var/railroad/{{host_role}}/shared/config/secrets.yml:
  file.managed:
    - source: salt://rails/secrets.yml
    - mode: 400
    - user: railroad-{{host_role}}
    - group: railroad-{{host_role}}
    - template: jinja
    - defaults:
        role: host_role
        db_username: m_u
        db_password: {{ salt['grains.get_or_set_hash']('some:place:secret_key_base') }}