Puppet模板嵌套迭代报错,如何正确生成sudo_authorized_keys文件?
背景与目标
我本周开始学习Puppet,想要把用户密钥写入/etc/ssh/sudo_authorized_keys文件。
数据存储(sudo_users.yaml)
core::sudo_users_keys: kate: keys: key1: type: "ssh-ed25519" key: "AAAAC3N..." john: keys: key1: type: "ssh-ed25519" key: "AAAAC..." marvin: keys: key1: type: "ssh-ed25519" key: "AAAAC3Nza..."
已编写的Puppet类(sudokeys.pp)
class core::sudokeys { file { "/etc/ssh/sudo_authorized_keys": ensure => file, mode => "0440", content => template("core/sudo_authorized_keys.erb"), } }
当前模板代码(sudo_authorized_keys.erb)
<%- scope['core::sudo_users_keys'].each | user | -%> { <%- if user[1] -%> <%- $user[1]['keys'].each do | key | -%> <%= $key[1]['type'] $key[1]['key'] -%> <%- end end -%> } <%- end -%>
参考可用代码(sshkeys类)
之前用相同数据结构配置用户ssh密钥时,这段代码可以正常工作,但无法直接用于生成sudo_authorized_keys文件,所以选择模板方式:
class core::sshkeys { lookup("core::sudo_users_keys").each | $user | { if $user[1] { $user[1]["keys"].each | $key | { ssh_authorized_key { "${user[0]}-${key[0]}": ensure => present, user => $user[0], type => $key[1]["type"], key => $key[1]["key"], } } } } }
遇到的错误
部署模板时出现语法错误:
Internal Server Error: org.jruby.exceptions.SyntaxError: (SyntaxError) /etc/puppetlabs/code/environments/test/modules/core/templates/sudo_authorized_keys.erb:2: syntax error, unexpected tSTRING_BEG _erbout<< " {\n".freeze ^
解决方案
你的模板存在多处语法问题,修正后的模板代码如下:
<%- scope.lookupvar('core::sudo_users_keys').each_pair |$username, $user_data| -%> <%- if $user_data['keys'] -%> <%- $user_data['keys'].each_pair |$key_name, $key_data| -%> <%= "${key_data['type']} ${key_data['key']}" -%> <%- end -%> <%- end -%> <%- end -%>
关键修改点:
- 遍历方式优化:使用
each_pair直接获取键值对(用户名和对应数据),替代原有的each+索引取值,代码更直观易读。 - 变量引用修正:Puppet ERB模板中变量无需加
$前缀,同时用scope.lookupvar()规范获取类变量。 - 格式与语法修复:原模板中密钥类型和内容缺少空格分隔,且多余
$前缀导致语法错误,修正后输出符合sudo_authorized_keys要求的每行一个密钥的格式(类型+空格+密钥内容)。 - 冗余符号移除:原模板中的
{}属于多余内容,直接输出密钥行即可,匹配文件格式要求。
可选扩展
如果需要在密钥后添加注释(比如关联用户名),可以修改输出行:
<%= "${key_data['type']} ${key_data['key']} ${username}" -%>
内容的提问来源于stack exchange,提问作者Brzozova
相关产品推荐
相关产品推荐

