扩展 Puppet(可能使用 augeas)以实现自定义配置格式

扩展 Puppet(可能使用 augeas)以实现自定义配置格式

我有一个自定义防火墙系统,其中包含我们自己的简单配置文件。它基本上是 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 轻松管理配置文件,甚至可以创建自定义提供程序。

相关内容