我安装了一个类似于(简化)的rails的配置:
production:
secret_key_base: 800afb35d5086b2c60ebd35c01b2bd2b522c2492
db_username: ...
db_password: ...
因此从模板文件安装
{{ role }}:
secret_key_base: {{ secret_key }}
db_username: {{ db_user }}
db_password: {{ db_pass }}
角色和db user / pass从支柱中拉出并安装在该文件中。 secret_key随机生成是有意义的,例如{{ salt['random.get_str'](length=80) }}
。但我希望生成一次,而不是每次渲染模板。 (更改密钥会使cookie无效,而不是每次盐运行都要做。)
我发现的唯一解决方案是两阶段:我有一个template.in
文件
{{ 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
。 (假设我们在秘密文件中添加了另一个密钥。)它也比必要时感觉更笨拙。
有更好的方法吗?
正如评论中所指出的,更好的方法是手工生成秘密(毕竟,它只在主机设置中完成)并将其存储在支柱中,我们无论如何都要说几件事关于每个主人。
以下是工作代码的最终结果,对于那些可能希望看到更复杂的内容的人来说,这些代码是未经简化的。很多复杂性是我的host_credentials
支柱数据,它试图描述我们需要了解的每个主机的所有信息。
{% 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是白空间不可知的,这对于这种查找的可读性非常有帮助。
答案 0 :(得分:2)
我建议将秘密放入支柱并在主设备上生成一次(手动)值。这样您就可以避免在SLS文件中执行有状态的动态魔法。
jma更新了他的问题以包含一个示例解决方案。
答案 1 :(得分:0)
我是否理解正确:
- 这是盐无主的运行?
- 在无主节点上生成一些模板文件(生成一些静态部分)
- 您将file.managed
状态应用于以前生成的文件吗?
假设我的理解:
首先,如果你设置了正确的watch/require
statements,将传播到其他州,但在你的情况下,由于你已经使用了{{1},这将更难实现用于模板解析(必须添加cmd.run
参数to express that there is some potential state changes underlying)
说明:
- 你看到了file.blockreplace
吗?您似乎可以使用它来替换第一个stateful
并获取文件更改检测"免费"
- 对于一次性密码生成,只需使用grains.get_or_set_hash
由于生成的密码没有针对给定的minion(您的情况下是无主节点)而更改,cmd.run
不会报告任何更改,除非您向模板添加更改
话虽如此,我认为我们可以更进一步,你的状态实际上可以像这样简单(模板更改将始终传播,密钥将生成一次):
file.blockreplace