我有一个自定义防火墙系统,其中包含我们自己的简单配置文件。它基本上是 bash 源,定义了一个众所周知的变量:
SUPERACCESS="127.0.0.1 192.168.11.0/24"
SERVICES="ping 80/tcp 443/tcp 22/tcp"
FORWARDING=1
.....
并且我希望使用 puppet 来管理这些配置文件(如果需要的话,可能通过 augeas)。因为我对整个 puppet 生态系统还不熟悉,所以我正在寻找一种相当简单、干净的“最佳实践”来实现这一点。
我需要能够仅修改部分选项(因此我无法从 Puppet Master 发送整个文件配置),并且我不想将这些文件的访问权限专门限制在 Puppet 上。我需要的是一种确保特定子网、服务等在(或不在)适当列表中的方法,即:
firewall::superaccess { "LAN" :
target => "192.168.11.0/24",
ensure=> "present",
}
我设法强制 augeas 使用 Shell_variables lens,并且能够更改“简单”字段,例如 FORWARDING。不幸的是,我无法使用 Shell_variables_list lens 成功处理列表值(即 SUPERACCESS)。
也许有比使用 augeas 更好的方法。我尝试在 puppet forge 上查找是否有具有类似配置格式的模块,但我没有找到。不幸的是,我不太了解 ruby 和 augeas 镜头语言,但如果需要,我会学习一些。我只是不想从错误的方向开始……
更新: 感谢 Raphink,我成功找到了问题所在。问题出在这行中间的注释上。如果文件中有以下一行:
service_ping="ping/icmp" #ping
我收到此错误:
/tmp/augcheck.TCTUBq/parse_file.aug:3.0-.58:exception thrown in test
/tmp/augcheck.TCTUBq/parse_file.aug:3.5-.54:exception: Iterated lens matched less than it should
Lens: /usr/share/augeas/lenses/dist/shellvars_list.aug:40.12-.37:
Error encountered at 176:0 (9906 characters into string)
<--------\n#Built in services\n|=|service_ping="ping/icmp" #pi>
Tree generated so far:
如果我将注释移到单独的行上,它会将文件加载到树结构中。甚至 augtool 也能按预期工作。我安装了以下版本的 augeas:ruby-augeas-0.4.1-3.fc17.x86_64、augeas-1.0.0-1.fc17.x86_64、augeas-libs-1.0.0-1.fc17.x86_64
更新 2: 为了解决内联注释的问题,我使用了 ShellVars lens 中的代码。更改是从 ShellVars 复制/粘贴一些定义并更改行的定义:
let empty_part_re = Util.empty_generic_re . /\n+/
let semicol_eol = del (/[ \t]*[;\n]/ . empty_part_re*) "\n"
let eol_for_comment = del /([ \t]*\n)([ \t]*(#[ \t]*)?\n)*/ "\n"
(* comment_eol in shell MUST begin with a space *)
let comment_eol = Util.comment_generic_seteol /[ \t]+#[ \t]*/ " # " eol_for_comment
let comment_or_eol = comment_eol | semicol_eol
let kv = [ key key_re . eq . ( squote_arr | dquote_arr | unquot_val ) . comment_or_eol ]
答案1
是的,Shellvars_list
镜头应该能够将您的文件解析为:
{ "SUPERACCESS"
{ "quote" = """ }
{ "value" = "127.0.0.1" }
{ "value" = "192.168.11.0/24" }
}
{ "SERVICES"
{ "quote" = """ }
{ "value" = "ping" }
{ "value" = "80/tcp" }
{ "value" = "443/tcp" }
{ "value" = "22/tcp" }
}
{ "FORWARDING"
{ "quote" = "" }
{ "value" = "1" }
}
注意:您可以使用以下方法进行测试augcheck
:
augcheck /etc/firewall/config Shellvars_list
现在,问题是:“如何从那棵树得到你的定义?”,即:
firewall::superaccess { "LAN" :
target => "192.168.11.0/24",
ensure=> "present",
}
您想确保列表中存在一个元素。
你可以这样做:
define firewall::superaccess (
$target,
$ensure = 'present',
) {
case $ensure {
'present': {
$changes = "set SUPERACCESS/value[.='${target}'] '${target}'"
}
'absent': {
$changes = "rm SUPERACCESS/value[.='${target}']"
}
default: { fail "Wrong value for ensure: '${ensure}'" }
}
augeas { "Set target ${target} in /etc/firewall/config":
lens => 'Shellvars_list.lns',
incl => '/etc/firewall/config',
changes => $changes,
}
}
答案2
我可能会做的是更改脚本,使变量来自外部文件,例如 /etc/sysconfig/firewall-info 或其他文件(例如在 redhat box 或类似设备上)。这样您就根本不需要修改或管理脚本,只需修改配置文件,然后让脚本从配置文件中读取变量。然后,您可以使用 augeas shellvars lens 轻松管理配置文件,甚至可以创建自定义提供程序。