From 24ee585f8b8bdbff51524fa58b019b9e78423854 Mon Sep 17 00:00:00 2001 From: Neil Hemingway Date: Thu, 19 Aug 2021 15:57:51 +0100 Subject: [PATCH 1/2] Refactor out common parts of helper process results parsing --- lib/dellos10/util.rb | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/dellos10/util.rb diff --git a/lib/dellos10/util.rb b/lib/dellos10/util.rb new file mode 100644 index 0000000..fca01c7 --- /dev/null +++ b/lib/dellos10/util.rb @@ -0,0 +1,38 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# Author:: Neil Hemingway (neil.hemingway@greyhavens.org.uk) +# Copyright:: Copyright (c) 2021, Dell Inc. All rights reserved. +# License:: [Apache License] (http://www.apache.org/licenses/LICENSE-2.0) +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require '/opt/dell/os10/bin/devops/dellos10_shell.rb' + +def get_instances_from_running_config(entity, &block) + res = [] + + begin + debug "Fetching #{entity} config..." + cmd = "show running-configuration #{entity} | display-xml" + hret = execute_show_command(cmd) + raise "No rpc-reply from '#{cmd}'" unless hret[:stdout] and hret[:stdout].length > 0 + data = hret[:stdout]['rpc-reply'][:data] + res = block.call(data) + info("#{entity} instances: #{res}") + res + rescue Exception => e + err 'Exception in get_instances_from_running_config' + err e.message + err "hret: #{hret}" + err e.backtrace[0] + raise + end + + res +end From a38d48804a7025aeac886deb88609594cd2780cd Mon Sep 17 00:00:00 2001 From: Neil Hemingway Date: Tue, 24 Aug 2021 16:38:23 +0100 Subject: [PATCH 2/2] Create os10_privilege resource Closes #12 --- .../provider/os10_privilege/dellos10.rb | 107 ++++++++++++++++++ lib/puppet/type/os10_privilege.rb | 89 +++++++++++++++ manifests/os10_privilege.pp | 3 + 3 files changed, 199 insertions(+) create mode 100644 lib/puppet/provider/os10_privilege/dellos10.rb create mode 100644 lib/puppet/type/os10_privilege.rb create mode 100644 manifests/os10_privilege.pp diff --git a/lib/puppet/provider/os10_privilege/dellos10.rb b/lib/puppet/provider/os10_privilege/dellos10.rb new file mode 100644 index 0000000..caabb79 --- /dev/null +++ b/lib/puppet/provider/os10_privilege/dellos10.rb @@ -0,0 +1,107 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# Author:: Neil Hemingway (neil.hemingway@greyhavens.org.uk) +# Copyright:: Copyright (c) 2018, Dell Inc. All rights reserved. +# License:: [Apache License] (http://www.apache.org/licenses/LICENSE-2.0) +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Sample definition for os10_privilege resource: +# +# os10_privilege { "$mode:$priv_level:$command": } + +require '/opt/dell/os10/bin/devops/dellos10_shell.rb' +require 'dellos10/util' + +Puppet::Type.type(:os10_privilege).provide(:dellos10) do + desc 'Dell Networking OS Privilege Provider' + + alias_method :esc, :execute_show_command + alias_method :ecc, :execute_config_command + + mk_resource_methods + + # Start the CLI shell server + start_os10_shell + + def self.get_privilege_properties(priv) + info("priv: #{priv}") + props = { + :priv_level => priv.delete(:level).to_i, + :ensure => :present, + } + priv[:mode].each_pair do |key, value| + case key + when :'mode-name' + props[:mode] = value + when :command + props[:command] = value + when :'permit-param' + props[:permit_param] = value + end + end + props[:name] = "#{props[:mode]}:#{props[:priv_level]}:#{props[:command]} #{props[:permit_param]}" + props + end + + def self.get_privileges(privileges) + privileges = privileges.fetch(:privilege, []) + privileges = [privileges] unless privileges.kind_of?(Array) + + privileges.map do |privilege| + privilege_properties = get_privilege_properties(privilege) + new(privilege_properties) + end + end + + def self.instances + get_instances_from_running_config 'privilege' do |data| + raise 'No users from "show run privilege"' unless data.has_key?(:'privilege-level-config') + get_privileges(data[:'privilege-level-config']) + end + end + + def self.prefetch(resources) + debug 'Prefetching users...' + instances.each do |prov| + if resource = resources[prov.name] + resource.provider = prov + end + end + end + + def exists? + @property_hash[:ensure] == :present + end + + def create + conf_lines = [] + cmd = "privilege #{resource[:mode]}" + cmd += " priv-lvl #{resource['priv_level']}" + cmd += " \"#{resource['command']} #{resource['permit_param']}\"" + conf_lines << cmd + + debug("(create) command: #{conf_lines}") + ecc conf_lines + end + + def destroy + conf_lines = [] + cmd = "no privilege #{resource[:mode]}" + cmd += " priv-lvl #{resource['priv_level']}" + cmd += " \"#{resource['command']} #{resource['permit_param']}\"" + conf_lines << cmd + debug("(destroy) conf_lines: #{conf_lines}") + ecc conf_lines + end + + def to_s + "#{@resource}(provider=#{self.class.name}, " + @property_hash.collect { |k,v| "#{k}=#{v}" }.join(', ') + ')' + end +end diff --git a/lib/puppet/type/os10_privilege.rb b/lib/puppet/type/os10_privilege.rb new file mode 100644 index 0000000..8dcaa54 --- /dev/null +++ b/lib/puppet/type/os10_privilege.rb @@ -0,0 +1,89 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# Author:: Neil Hemingway (neil.hemingway@greyhavens.org.uk) +# Copyright:: Copyright (c) 2018, Dell Inc. All rights reserved. +# License:: [Apache License] (http://www.apache.org/licenses/LICENSE-2.0) +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Resource definition for managing NTP configuration in OS10 operating system +# running in a Dell EMC Networking device. +# +# Sample configuration: +# +# os10_privilege { "$mode:$priv_level:$command": } + +Puppet::Type.newtype(:os10_privilege) do + desc 'os10_privilege resource type is to used to manage privilege levels in + OS10 EE switches' + + ensurable + + newparam(:name) do + desc 'The ephemeral name of the resource.' + end + + newproperty(:mode, namevar: true) do + desc 'The privilege mode used to access CLI modes.' + + newvalues('exec', 'configure', 'interface', 'route-map', 'router', 'line') + end + + newproperty(:priv_level, namevar: true) do + desc 'An integer specifying the privilege level to use for the account.' + + munge do |value| + info("Munging priv_level #{value} (#{value.class})") + case value + when Integer + raise ArgumentError, 'priv_level must be an integer between 1-15 (inclusive)' unless 1 <= value and value <= 15 + return value + when String + if value =~ /^\d+$/ + int_value = value.to_i + raise ArgumentError, 'priv_level must be an integer between 1-15 (inclusive)' unless 1 <= int_value and int_value <= 15 + return int_value + else + raise Puppet::Error, _("The priv_level specification is invalid: %{value}") % { value: value.inspect } + end + else + raise Puppet::Error, _("The priv_level specification is invalid: %{value}") % { value: value.inspect } + end + end + end + + newproperty(:command, namevar: true) do + desc 'The command to be supported at the privilege level.' + end + + newproperty(:permit_param, namevar: true) do + desc 'The command parameter to be supported at the privilege level.' + end + + def self.title_patterns + [ + [ + /^(([^:]+):([^:]+):(\S+)\s(.*))$/, + [ + [ :name ], + [ :mode ], + [ :priv_level ], + [ :command ], + [ :permit_param ], + ] + ], + [ + /(.*)/, + [ + [ :name ], + ] + ] + ] + end +end diff --git a/manifests/os10_privilege.pp b/manifests/os10_privilege.pp new file mode 100644 index 0000000..b72db48 --- /dev/null +++ b/manifests/os10_privilege.pp @@ -0,0 +1,3 @@ +# Sample manifest file for os10_privilege resource + +os10_privilege { "$mode:$priv_level:$command": }