diff --git a/lib/puppet/provider/panos_address/panos_address.rb b/lib/puppet/provider/panos_address/panos_address.rb index 4ccd71f3..199e9f79 100644 --- a/lib/puppet/provider/panos_address/panos_address.rb +++ b/lib/puppet/provider/panos_address/panos_address.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_address type using the Resource API. -class Puppet::Provider::PanosAddress::PanosAddress < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosAddress::PanosAddress < Puppet::Provider::PanosVsysBase def validate_should(should) required = [should[:ip_netmask], should[:ip_range], should[:fqdn]].compact.size if required > 1 # rubocop:disable Style/GuardClause diff --git a/lib/puppet/provider/panos_address_group/panos_address_group.rb b/lib/puppet/provider/panos_address_group/panos_address_group.rb index 5e453435..e1124856 100644 --- a/lib/puppet/provider/panos_address_group/panos_address_group.rb +++ b/lib/puppet/provider/panos_address_group/panos_address_group.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_address_group type using the Resource API. -class Puppet::Provider::PanosAddressGroup::PanosAddressGroup < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosAddressGroup::PanosAddressGroup < Puppet::Provider::PanosVsysBase def validate_should(should) if should[:type] == 'static' && !should.key?(:static_members) raise Puppet::ResourceError, 'Static Address group must provide `static_members`' diff --git a/lib/puppet/provider/panos_nat_policy/panos_nat_policy.rb b/lib/puppet/provider/panos_nat_policy/panos_nat_policy.rb index 29a0c4c6..f5f38b8e 100644 --- a/lib/puppet/provider/panos_nat_policy/panos_nat_policy.rb +++ b/lib/puppet/provider/panos_nat_policy/panos_nat_policy.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_NAT_policy type using the Resource API. -class Puppet::Provider::PanosNatPolicy::PanosNatPolicy < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosNatPolicy::PanosNatPolicy < Puppet::Provider::PanosVsysBase def munge(entry) entry[:bi_directional] = string_to_bool(entry[:bi_directional]) unless entry[:bi_directional].nil? entry[:nat_type] = 'ipv4' if entry[:nat_type].nil? diff --git a/lib/puppet/provider/panos_security_policy_rule/panos_security_policy_rule.rb b/lib/puppet/provider/panos_security_policy_rule/panos_security_policy_rule.rb index a33ced9d..fb3364b6 100644 --- a/lib/puppet/provider/panos_security_policy_rule/panos_security_policy_rule.rb +++ b/lib/puppet/provider/panos_security_policy_rule/panos_security_policy_rule.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_security_policy_rule type using the Resource API. -class Puppet::Provider::PanosSecurityPolicyRule::PanosSecurityPolicyRule < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosSecurityPolicyRule::PanosSecurityPolicyRule < Puppet::Provider::PanosVsysBase def munge(entry) none_attrs = [:profile_type, :qos_type] diff --git a/lib/puppet/provider/panos_service/panos_service.rb b/lib/puppet/provider/panos_service/panos_service.rb index eb497d2f..d61d54d8 100644 --- a/lib/puppet/provider/panos_service/panos_service.rb +++ b/lib/puppet/provider/panos_service/panos_service.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_service_type type using the Resource API. -class Puppet::Provider::PanosService::PanosService < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosService::PanosService < Puppet::Provider::PanosVsysBase def xml_from_should(name, should) builder = Builder::XmlMarkup.new builder.entry('name' => name) do diff --git a/lib/puppet/provider/panos_service_group/panos_service_group.rb b/lib/puppet/provider/panos_service_group/panos_service_group.rb index bf815b0a..96d64f08 100644 --- a/lib/puppet/provider/panos_service_group/panos_service_group.rb +++ b/lib/puppet/provider/panos_service_group/panos_service_group.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_service_group type using the Resource API. -class Puppet::Provider::PanosServiceGroup::PanosServiceGroup < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosServiceGroup::PanosServiceGroup < Puppet::Provider::PanosVsysBase def xml_from_should(name, should) builder = Builder::XmlMarkup.new builder.entry('name' => name) do diff --git a/lib/puppet/provider/panos_tag/panos_tag.rb b/lib/puppet/provider/panos_tag/panos_tag.rb index 77a71091..3f805fa1 100644 --- a/lib/puppet/provider/panos_tag/panos_tag.rb +++ b/lib/puppet/provider/panos_tag/panos_tag.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_tags type using the Resource API. -class Puppet::Provider::PanosTag::PanosTag < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosTag::PanosTag < Puppet::Provider::PanosVsysBase def initialize super() @code_from_color = { diff --git a/lib/puppet/provider/panos_vsys_base.rb b/lib/puppet/provider/panos_vsys_base.rb new file mode 100644 index 00000000..244ac7ef --- /dev/null +++ b/lib/puppet/provider/panos_vsys_base.rb @@ -0,0 +1,97 @@ +require_relative 'panos_provider' + +# A base provider for all PANOS providers inside a VSYS +class Puppet::Provider::PanosVsysBase < Puppet::Provider::PanosProvider + def set(context, changes) + changes.each do |name, change| + is = if context.type.feature?('simple_get_filter') + change.key?(:is) ? change[:is] : (get(context, [name]) || []).find { |r| r[:name] == name } + else + change.key?(:is) ? change[:is] : (get(context) || []).find { |r| r[:name] == name } + end + context.type.check_schema(is) unless change.key?(:is) + + should = change[:should] + + raise 'SimpleProvider cannot be used with a Type that is not ensurable' unless context.type.ensurable? + + is = SimpleProvider.create_absent(:name, name) if is.nil? + should = SimpleProvider.create_absent(:name, name) if should.nil? + + name_hash = if context.type.namevars.length > 1 + # pass a name_hash containing the values of all namevars + name_hash = {} + context.type.namevars.each do |namevar| + name_hash[namevar] = change[:should][namevar] + end + name_hash + else + name + end + + if is[:ensure].to_s == 'absent' && should[:ensure].to_s == 'present' + context.creating(name) do + create(context, name_hash, should) + end + elsif is[:ensure].to_s == 'present' && should[:ensure].to_s == 'present' + context.updating(name) do + update(context, name_hash, should, is) + end + elsif is[:ensure].to_s == 'present' && should[:ensure].to_s == 'absent' + context.deleting(name) do + delete(context, name_hash) + end + end + end + end + + def get(context) + results = [] + config = context.transport.get_config('/config/devices/entry/vsys/entry') + config.elements.collect('/response/result/entry') do |vsys_entry| # rubocop:disable Style/CollectionMethods + result = {} + vsys = match(vsys_entry, { xpath: 'string(@name)' }, 'name') + vsys_entry.elements.collect("/response/result/entry/#{context.type.definition[:base_xpath]}/entry") do |entry| # rubocop:disable Style/CollectionMethods + result = {} + context.type.attributes.each do |attr_name, attr| + result[attr_name] = match(entry, attr, attr_name) + end + result[:vsys] = vsys + results << result + end + end + results + end + + def create(context, name, should) + validate_should(should) if defined? validate_should + xpath = if should[:vsys] + "/config/devices/entry/vsys/entry[@name='#{should[:vsys]}']/#{context.type.definition[:base_xpath]}" + else + "/config/devices/entry/vsys/entry/#{context.type.definition[:base_xpath]}" + end + context.transport.set_config(xpath, xml_from_should(name, should)) + context.transport.move(context.type.definition[:base_xpath], name, should[:insert_after]) unless should[:insert_after].nil? + end + + def update(context, name, should, is) + validate_should(should) if defined? validate_should + if should[:vsys] == is[:vsys] + xpath = if should[:vsys] + "/config/devices/entry/vsys/entry[@name='#{should[:vsys]}']/#{context.type.definition[:base_xpath]}/entry[@name='#{name}']" + else + "/config/devices/entry/vsys/entry/#{context.type.definition[:base_xpath]}/entry[@name='#{name}']" + end + + context.transport.edit_config("#{xpath}/entry[@name='#{name}']", xml_from_should(name, should)) + context.transport.move(context.type.definition[:base_xpath], name, should[:insert_after]) unless should[:insert_after].nil? + else + delete(context, name) + create(context, name, should) + end + end + + def delete(context, name) + context.transport.delete_config("/config/devices/entry/vsys/entry/#{context.type.definition[:base_xpath]}/entry[@name='#{name}']") + end +end diff --git a/lib/puppet/provider/panos_zone/panos_zone.rb b/lib/puppet/provider/panos_zone/panos_zone.rb index a0c87c3d..d67cfe70 100644 --- a/lib/puppet/provider/panos_zone/panos_zone.rb +++ b/lib/puppet/provider/panos_zone/panos_zone.rb @@ -1,7 +1,7 @@ -require_relative '../panos_provider' +require_relative '../panos_vsys_base' # Implementation for the panos_tags type using the Resource API. -class Puppet::Provider::PanosZone::PanosZone < Puppet::Provider::PanosProvider +class Puppet::Provider::PanosZone::PanosZone < Puppet::Provider::PanosVsysBase def munge(entry) bool_attrs = [:enable_user_identification, :enable_packet_buffer_protection, :nsx_service_profile] bool_attrs.each do |attr| diff --git a/lib/puppet/type/panos_address.rb b/lib/puppet/type/panos_address.rb index aea621d7..be392ff4 100644 --- a/lib/puppet/type/panos_address.rb +++ b/lib/puppet/type/panos_address.rb @@ -5,7 +5,7 @@ docs: <<-EOS, This type provides Puppet with the capabilities to manage "address" objects on Palo Alto devices. EOS - base_xpath: '/config/devices/entry/vsys/entry/address', + base_xpath: 'address', features: ['remote_resource'], attributes: { name: { @@ -14,6 +14,10 @@ behaviour: :namevar, xpath: 'string(@name)', }, + vsys: { + type: 'Optional[String]', + desc: 'The vsys of the addresses xpath.', + }, ensure: { type: 'Enum[present, absent]', desc: 'Whether this resource should be present or absent on the target system.', diff --git a/lib/puppet/type/panos_address_group.rb b/lib/puppet/type/panos_address_group.rb index da7fa22c..5be0d3af 100644 --- a/lib/puppet/type/panos_address_group.rb +++ b/lib/puppet/type/panos_address_group.rb @@ -5,7 +5,7 @@ docs: <<-EOS, This type provides Puppet with the capabilities to manage "address_groups" objects on Palo Alto devices. EOS - base_xpath: '/config/devices/entry/vsys/entry/address-group', + base_xpath: 'address-group', features: ['remote_resource'], attributes: { name: { @@ -19,6 +19,10 @@ desc: 'Whether this resource should be present or absent on the target system.', default: 'present', }, + vsys: { + type: 'Optional[String]', + desc: 'The vsys of the address groups xpath.', + }, description: { type: 'Optional[String]', desc: 'Provide a description of this address-group.', diff --git a/lib/puppet/type/panos_nat_policy.rb b/lib/puppet/type/panos_nat_policy.rb index c0bb57cf..f39c966e 100644 --- a/lib/puppet/type/panos_nat_policy.rb +++ b/lib/puppet/type/panos_nat_policy.rb @@ -5,7 +5,7 @@ docs: <<-EOS, This type provides Puppet with the capabilities to manage "NAT Policy Rule" objects on Palo Alto devices. EOS - base_xpath: '/config/devices/entry/vsys/entry/rulebase/nat/rules', + base_xpath: 'rulebase/nat/rules', features: ['remote_resource'], attributes: { name: { @@ -24,6 +24,10 @@ desc: 'A description of the NAT Policy Rule', xpath: 'description/text()', }, + vsys: { + type: 'Optional[String]', + desc: 'The vsys of the policies xpath.', + }, nat_type: { type: 'Enum["ipv4", "nat64", "nptv6"]', desc: 'The nat type of the policy', diff --git a/lib/puppet/type/panos_security_policy_rule.rb b/lib/puppet/type/panos_security_policy_rule.rb index 975d7c62..3e60dd3a 100644 --- a/lib/puppet/type/panos_security_policy_rule.rb +++ b/lib/puppet/type/panos_security_policy_rule.rb @@ -5,7 +5,7 @@ docs: <<-EOS, This type provides Puppet with the capilities to manage "Security Policy Rules" on Palo Alto devices. EOS - base_xpath: '/config/devices/entry/vsys/entry/rulebase/security/rules', + base_xpath: 'rulebase/security/rules', features: ['remote_resource'], attributes: { name: { @@ -19,6 +19,10 @@ desc: 'Whether this resource should be present or absent on the target system.', default: 'present', }, + vsys: { + type: 'Optional[String]', + desc: 'The vsys of the rules xpath.', + }, rule_type: { type: 'Enum["universal", "interzone", "intrazone"]', desc: <