Поваренная книга брандмауэра Chef не работает с пользовательскими объектами JSON - PullRequest
0 голосов
/ 22 января 2019

Я играю с кулинарной книгой брандмауэра : cookbook 'firewall', '~> 2.7.0'

Не уверен, что это только я, но инструкции не очень понятны, но я дал ему старую попытку колледжа ...

Я пытаюсь создать рецепт, который позволит мне использовать data_bags и окружения для определения правил. Большинство узлов будет CentOS 7, но у меня также есть несколько Ubuntu 16 (возможно, разные версии ожидают стороннего программного обеспечения). Большинство узлов будут иметь 2 сетевых адаптера, один с зоной public, а другой с trusted. В связи с этим я бы предпочел придерживаться поваренной книги firewall, если это возможно.

Во время разработки я использовал rspec, и все работало как положено. Когда я пошел на Test Kitchen, тогда я узнал, что ничего не работает. Поэтому я залез в узел и понял, что правила не применяются.

В идеале сначала я хочу, чтобы зона по умолчанию была :public. Затем я хотел применить правила к каждой зоне из объектов json. При тестировании с rspec все выглядело хорошо. Когда я использовал Test Kitchen, ничего не происходило.

Надеюсь, я просто делаю глупости. Я надеюсь на толчок в правильном направлении здесь ... Следует отметить, что я начал это некоторое время назад и остановился из-за другого проекта. Теперь я вернулся к этому и пытаюсь определить проблемы.

Спасибо за ваше время.

Пример окружения (dev):

{
  "name": "dev",
  "description": "DEV Environment for Nodes",
  "chef_type": "environment",
  "json_class": "Chef::Environment",
  "default_attributes": {
    "oly": {
      "environment": "dev",
      "type" : "node",
      "firewall": {
        "status": "enabled",
        "zones": {
          "public": {
            "22": {
              "private_ip_1": "10.0.0.0/8",
              "private_ip_2": "172.16.0.0/12",
              "private_ip_3": "192.168.0.0/16",
              "private_ip_4": "169.254.0.0/16",
              "private_ip_5": "100.64.0.0/10"
            }
          }
        }
      }
    }
  },
  "cookbook_versions": {
    "oly-client": "= 4.0.0"
  }
}

В вышеуказанной среде есть конфигурация зоны брандмауэра, которая открывает порт 22 для всех частных IP-адресов.

Пример data_bag (межсетевой экран: глобальный):

{
  "id": "global",
  "zones": {
    "public": {
      "22": {
          "office_1": "1.1.1.1/32",
          "office_2": "2.2.2.2/32",
          "office_3": "3.3.3.3/32",
          "office_4": "4.4.4.4/32",
          "office_5": "5.5.5.5/32"
      }
    }
  }
}

В идеале это позволяет применять глобальные правила к рецепту.

Поваренная книга, над которой я работаю:

#
# Cookbook:: oly-client
# Recipe:: firewall
# 
# TODO: Create a method to optimize code (code repetition is real here)

# Fetch firewall settings
_firewallSettings = node['oly']['firewall']

# Make sure we have firewall settings and that they are enabled
if (!_firewallSettings.to_a.empty? && _firewallSettings.key?("status") && 'enabled' == _firewallSettings['status'].downcase)
  # include the base firewall recipe
  include_recipe "firewall::default"

  # Enable platform default firewall and set default zone
  firewall "default" do
    action [:install]
    enabled_zone :public
  end

  # START global firewall rules
  _globalFirewallRules = data_bag_item('firewall', 'global')
  if (_globalFirewallRules && _globalFirewallRules.key?("zones"))

    # Loop over each firewall zone and build rules from data
    _globalFirewallRules['zones'].each do |_zone, _zoneData|

      # Ensure we have zone data
      if (_zoneData)

        # Ensure the firewall is installed for the zone
        firewall "#{_zone}" do
          enabled_zone "#{_zone}".to_sym
          action [:install]
        end

        # Process rules for firewall
        _zoneData.each do |_port, _portRules|
          # Verify rules exist
          if (_portRules)
            # Build rules
            _portRules.each do |_ipComment, _ipAddress|

              # Define rule
              firewall_rule "#{_zone} - #{_port}: #{_ipComment} - #{_ipAddress}" do
                firewall_name "#{_zone}"
                port _port.to_i
                source _ipAddress
                direction :in
                command :allow
              end

            end
          end
        end

        # Save the firewall settings
        firewall "#{_zone}" do
          # action :save
          action [:save]
        end

      end

    end

  end
  # END global firewall rules

  # Check if environment has any zones configured
  if (_firewallSettings.key?("zones"))

    # Loop over each firewall zone and build rules from data
    _firewallSettings['zones'].each do |_zone, _zoneData|

      # Ensure we have zone data
      if (_zoneData)

        # Ensure the firewall is installed for the zone (in case global zones does not include)
        firewall "#{_zone}" do
          enabled_zone "#{_zone}".to_sym
          # action :install
          action [:install]
        end

        # Process rules for firewall
        _zoneData.each do |_port, _portRules|
          # Verify rules exist
          if (_portRules)
            # Build rules
            _portRules.each do |_ipComment, _ipAddress|

              # Define rule
              firewall_rule "#{_zone} - #{_port}: #{_ipComment} - #{_ipAddress}" do
                firewall_name "#{_zone}"
                port _port.to_i
                source _ipAddress
                direction :in
                command :allow
              end

            end
          end
        end

        # Save the firewall settings
        firewall "#{_zone}" do
          # action :save
          action [:save]
        end

      end

    end


  end
  # END environment firewall rules

  # TODO Add logic for custom rules (with search capabilites, like users - Did not do yet as this is edge case if needed at all)

  # Save the firewall settings
  firewall "default" do
    # action :save
    action [:save]
  end

else
  # Firewall is disabled unless explicitly enabled
  include_recipe 'firewall::disable_firewall'
end

Мой тест rspec (поменял IP-адреса, но должен работать так же):

#
# Cookbook:: oly-client
# Spec:: default
#
# Copyright:: 2017, The Authors, All Rights Reserved.

require 'spec_helper'

describe 'oly-client::firewall' do

  context 'on CentOS 7 Latest' do

    let(:chef_run) do
      ChefSpec::SoloRunner.new(platform: 'centos', version: '7') do |node|

        # Build node attributes for tests
        node.normal['oly']['firewall']['status'] = "enabled"
        node.normal['oly']['firewall']['zones'] = {
          "public": {
            "22": {
              "private_ip_1": "10.0.0.0/8",
              "private_ip_2": "172.16.0.0/12",
              "private_ip_3": "192.168.0.0/16",
              "private_ip_4": "169.254.0.0/16"
            }
          },
          "trusted": {
            "22": {
              "private_ip_5": "100.64.0.0/10"
            }
          }
        }

        # Firewall rules
        node.normal['firewall']['allow_icmp'] = true
        node.normal['firewall']['allow_ssh'] = true
        node.normal['firewall']['allow_winrm'] = false
        node.normal['firewall']['allow_mosh'] = false

      end.converge(described_recipe)
    end

    # Stub databags
    before do
      stub_data_bag('firewall').and_return(['global'])
      stub_data_bag_item('firewall', 'global').and_return({
        "id": "global",
        "zones": {
          "public": {
            "22": {
                  "office_1": "1.1.1.1/32",
                  "office_2": "2.2.2.2/32",
                  "office_3": "3.3.3.3/32"
            }
          },
          "trusted": {
            "22": {
              "office_1": "1.1.1.1/32",
              "office_3": "3.3.3.3/32",
              "office_4": "4.4.4.4/32",
              "office_5": "5.5.5.5/32"
            }
          }
        }
      })
    end

    it 'include the recipe to enable firewall' do
      expect(chef_run).to include_recipe('firewall::default')
    end

    it 'enables the firewall' do
      expect(chef_run).to install_firewall('public')
      expect(chef_run).to install_firewall('trusted')
    end

    it 'creates some rules' do
      _rules = [
        "allow loopback", 
        "allow icmp", 
        "allow world to ssh", 
        "established",
        "ipv6_icmp",
        "public - 22: private_ip_1 - 10.0.0.0/8",
        "public - 22: private_ip_2 - 172.16.0.0/12",
        "public - 22: private_ip_3 - 192.168.0.0/16",
        "public - 22: private_ip_4 - 169.254.0.0/16",
        "trusted - 22: private_ip_5 - 100.64.0.0/10",
        "public - 22: office_1 - 1.1.1.1/32",
        "public - 22: office_2 - 2.2.2.2/32",
        "public - 22: office_3 - 3.3.3.3/32",
        "trusted - 22: office_1 - 1.1.1.1/32",
        "trusted - 22: office_3 - 3.3.3.3/32",
        "trusted - 22: office_4 - 4.4.4.4/32",
        "trusted - 22: office_5 - 5.5.5.5/32"
      ]

      _rules.each do |r|
        expect(chef_run).to create_firewall_rule(r)
      end
    end


    it 'not to creates some rules' do
      _rules = [
        "allow world to winrm", 
        "allow world to mosh",
        "public - 22: office_4 - 4.4.4.4/32",
        "public - 22: office_5 - 5.5.5.5/32",
        "trusted - 22: office_2 - 2.2.2.2/32"
      ]

      _rules.each do |r|
        expect(chef_run).to_not create_firewall_rule(r)
      end
    end

  end

end

1 Ответ

0 голосов
/ 25 января 2019

Зоны в настоящее время не поддерживаются в кулинарной книге.Я отправил PR , чтобы добавить поддержку.Хотя документация по кулинарной книге не совсем понятна, проблемы, которые я здесь разместил, связаны с отсутствием функции firewalld.

...