diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 1c4f916..f817339 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -10,24 +10,25 @@ jobs: strategy: matrix: puppet: - - label: 'Puppet 6' - puppet_version: '~> 6' - ruby_version: '2.5' - - label: 'Puppet 7' - puppet_version: '~> 7' - ruby_version: '2.7' + - label: 'OpenVox 8 (Ruby 3.2)' + puppet_version: '~> 8.0' + ruby_version: '3.2' + - label: 'OpenVox 8 (Ruby 4.0)' + puppet_version: '~> 8.0' + ruby_version: '4.0' env: - PUPPET_GEM_VERSION: ${{matrix.puppet.puppet_version}} + PUPPET_VERSION: ${{matrix.puppet.puppet_version}} BUNDLE_WITHOUT: 'acceptance:system_tests' steps: - - uses: actions/checkout@v2 - - name: Install libcurl dev headers (needed to build the patron gem pulled in by faraday-patron) - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.puppet.ruby_version}} bundler-cache: true - - run: bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop + # check:symlinks is intentionally omitted here: that rake task no longer + # exists under the voxpupuli-test toolchain (confirmed via `rake --tasks`), + # unlike check:git_ignore/check:dot_underscore/check:test_file, which do. + - run: bundle exec rake syntax lint metadata_lint check:git_ignore check:dot_underscore check:test_file rubocop parallel_spec: needs: @@ -36,19 +37,17 @@ jobs: strategy: matrix: puppet: - - label: 'Puppet 6' - puppet_version: '~> 6' - ruby_version: '2.5' - - label: 'Puppet 7' - puppet_version: '~> 7' - ruby_version: '2.7' + - label: 'OpenVox 8 (Ruby 3.2)' + puppet_version: '~> 8.0' + ruby_version: '3.2' + - label: 'OpenVox 8 (Ruby 4.0)' + puppet_version: '~> 8.0' + ruby_version: '4.0' env: - PUPPET_GEM_VERSION: ${{matrix.puppet.puppet_version}} + PUPPET_VERSION: ${{matrix.puppet.puppet_version}} BUNDLE_WITHOUT: 'acceptance:system_tests' steps: - - uses: actions/checkout@v2 - - name: Install libcurl dev headers (needed to build the patron gem pulled in by faraday-patron) - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.puppet.ruby_version}} diff --git a/.rubocop.yml b/.rubocop.yml index 25fe076..3386144 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,23 +1,10 @@ --- -require: -- rubocop-performance -- rubocop-rspec +inherit_gem: + voxpupuli-test: rubocop.yml + AllCops: - DisplayCopNames: true - TargetRubyVersion: '2.4' - Include: - - "**/*.rb" - Exclude: - - bin/* - - ".vendor/**/*" - - "**/Gemfile" - - "**/Rakefile" - - pkg/**/* - - spec/fixtures/**/* - - vendor/**/* - - "**/Puppetfile" - - "**/Vagrantfile" - - "**/Guardfile" + TargetRubyVersion: 3.2 + Layout/LineLength: Description: People have wide screens, use them. Max: 200 @@ -73,8 +60,8 @@ Style/TrailingCommaInArrayLiteral: Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets -Style/AccessorMethodName: - Description: Do not prefix method names iwth `set_` or `get_`. Need to ignore non-ruby +Naming/AccessorMethodName: + Description: Do not prefix method names with `set_` or `get_`. Need to ignore non-ruby class files Exclude: - spec/**/* @@ -91,441 +78,13 @@ Style/Documentation: - spec/**/* Style/WordArray: EnforcedStyle: brackets -Performance/AncestorsInclude: - Enabled: true -Performance/BigDecimalWithNumericArgument: - Enabled: true -Performance/BlockGivenWithExplicitBlock: - Enabled: true -Performance/CaseWhenSplat: - Enabled: true -Performance/ConstantRegexp: - Enabled: true -Performance/MethodObjectAsBlock: - Enabled: true -Performance/RedundantSortBlock: - Enabled: true -Performance/RedundantStringChars: - Enabled: true -Performance/ReverseFirst: - Enabled: true -Performance/SortReverse: - Enabled: true -Performance/Squeeze: - Enabled: true -Performance/StringInclude: - Enabled: true -Performance/Sum: - Enabled: true -Style/CollectionMethods: - Enabled: true -Style/MethodCalledOnDoEndBlock: - Enabled: true -Style/StringMethods: - Enabled: true -Bundler/InsecureProtocolSource: - Enabled: false -Gemspec/DuplicatedAssignment: - Enabled: false -Gemspec/OrderedDependencies: - Enabled: false -Gemspec/RequiredRubyVersion: - Enabled: false -Gemspec/RubyVersionGlobalsUsage: - Enabled: false -Layout/ArgumentAlignment: - Enabled: false -Layout/BeginEndAlignment: - Enabled: false -Layout/ClosingHeredocIndentation: - Enabled: false -Layout/EmptyComment: - Enabled: false -Layout/EmptyLineAfterGuardClause: - Enabled: false -Layout/EmptyLinesAroundArguments: - Enabled: false -Layout/EmptyLinesAroundAttributeAccessor: - Enabled: false -Layout/EndOfLine: - Enabled: false -Layout/FirstArgumentIndentation: - Enabled: false -Layout/HashAlignment: - Enabled: false -Layout/HeredocIndentation: - Enabled: false -Layout/LeadingEmptyLines: - Enabled: false -Layout/SpaceAroundMethodCallOperator: - Enabled: false -Layout/SpaceInsideArrayLiteralBrackets: - Enabled: false -Layout/SpaceInsideReferenceBrackets: - Enabled: false -Lint/BigDecimalNew: - Enabled: false -Lint/BooleanSymbol: - Enabled: false -Lint/ConstantDefinitionInBlock: - Enabled: false -Lint/DeprecatedOpenSSLConstant: - Enabled: false -Lint/DisjunctiveAssignmentInConstructor: - Enabled: false -Lint/DuplicateElsifCondition: - Enabled: false -Lint/DuplicateRequire: - Enabled: false -Lint/DuplicateRescueException: - Enabled: false -Lint/EmptyConditionalBody: - Enabled: false -Lint/EmptyFile: - Enabled: false -Lint/ErbNewArguments: - Enabled: false -Lint/FloatComparison: - Enabled: false -Lint/HashCompareByIdentity: - Enabled: false -Lint/IdentityComparison: - Enabled: false -Lint/InterpolationCheck: - Enabled: false -Lint/MissingCopEnableDirective: - Enabled: false -Lint/MixedRegexpCaptureTypes: - Enabled: false -Lint/NestedPercentLiteral: - Enabled: false -Lint/NonDeterministicRequireOrder: - Enabled: false -Lint/OrderedMagicComments: - Enabled: false -Lint/OutOfRangeRegexpRef: - Enabled: false -Lint/RaiseException: - Enabled: false -Lint/RedundantCopEnableDirective: - Enabled: false -Lint/RedundantRequireStatement: - Enabled: false -Lint/RedundantSafeNavigation: - Enabled: false -Lint/RedundantWithIndex: - Enabled: false -Lint/RedundantWithObject: - Enabled: false -Lint/RegexpAsCondition: - Enabled: false -Lint/ReturnInVoidContext: - Enabled: false -Lint/SafeNavigationConsistency: - Enabled: false -Lint/SafeNavigationWithEmpty: - Enabled: false -Lint/SelfAssignment: - Enabled: false -Lint/SendWithMixinArgument: - Enabled: false -Lint/ShadowedArgument: - Enabled: false -Lint/StructNewOverride: - Enabled: false -Lint/ToJSON: - Enabled: false -Lint/TopLevelReturnWithArgument: - Enabled: false -Lint/TrailingCommaInAttributeDeclaration: - Enabled: false -Lint/UnreachableLoop: - Enabled: false -Lint/UriEscapeUnescape: - Enabled: false -Lint/UriRegexp: - Enabled: false -Lint/UselessMethodDefinition: - Enabled: false -Lint/UselessTimes: - Enabled: false -Metrics/AbcSize: - Enabled: false -Metrics/BlockLength: - Enabled: false -Metrics/BlockNesting: - Enabled: false -Metrics/ClassLength: - Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false -Metrics/MethodLength: - Enabled: false -Metrics/ModuleLength: - Enabled: false -Metrics/ParameterLists: - Enabled: false -Metrics/PerceivedComplexity: - Enabled: false -Migration/DepartmentName: - Enabled: false -Naming/AccessorMethodName: - Enabled: false -Naming/BlockParameterName: - Enabled: false -Naming/HeredocDelimiterCase: - Enabled: false -Naming/HeredocDelimiterNaming: - Enabled: false -Naming/MemoizedInstanceVariableName: - Enabled: false -Naming/MethodParameterName: - Enabled: false -Naming/RescuedExceptionsVariableName: - Enabled: false -Naming/VariableNumber: - Enabled: false -Performance/BindCall: - Enabled: false -Performance/DeletePrefix: - Enabled: false -Performance/DeleteSuffix: - Enabled: false -Performance/InefficientHashSearch: - Enabled: false -Performance/UnfreezeString: - Enabled: false -Performance/UriDefaultParser: - Enabled: false -RSpec/Be: - Enabled: false -RSpec/Capybara/CurrentPathExpectation: - Enabled: false -RSpec/Capybara/FeatureMethods: - Enabled: false -RSpec/Capybara/VisibilityMatcher: - Enabled: false -RSpec/ContextMethod: - Enabled: false -RSpec/ContextWording: - Enabled: false -RSpec/DescribeClass: - Enabled: false -RSpec/EmptyHook: - Enabled: false -RSpec/EmptyLineAfterExample: - Enabled: false -RSpec/EmptyLineAfterExampleGroup: - Enabled: false -RSpec/EmptyLineAfterHook: - Enabled: false -RSpec/ExampleLength: - Enabled: false -RSpec/ExampleWithoutDescription: - Enabled: false -RSpec/ExpectChange: - Enabled: false -RSpec/ExpectInHook: - Enabled: false -RSpec/FactoryBot/AttributeDefinedStatically: - Enabled: false -RSpec/FactoryBot/CreateList: - Enabled: false -RSpec/FactoryBot/FactoryClassName: - Enabled: false -RSpec/HooksBeforeExamples: - Enabled: false -RSpec/ImplicitBlockExpectation: - Enabled: false -RSpec/ImplicitSubject: - Enabled: false -RSpec/LeakyConstantDeclaration: - Enabled: false -RSpec/LetBeforeExamples: - Enabled: false -RSpec/MissingExampleGroupArgument: - Enabled: false -RSpec/MultipleExpectations: - Enabled: false RSpec/MultipleMemoizedHelpers: - Enabled: false -RSpec/MultipleSubjects: - Enabled: false -RSpec/NestedGroups: - Enabled: false -RSpec/PredicateMatcher: - Enabled: false -RSpec/ReceiveCounts: - Enabled: false -RSpec/ReceiveNever: - Enabled: false -RSpec/RepeatedExampleGroupBody: - Enabled: false -RSpec/RepeatedExampleGroupDescription: - Enabled: false -RSpec/RepeatedIncludeExample: - Enabled: false -RSpec/ReturnFromStub: - Enabled: false -RSpec/SharedExamples: - Enabled: false -RSpec/StubbedMock: - Enabled: false -RSpec/UnspecifiedException: - Enabled: false -RSpec/VariableDefinition: - Enabled: false -RSpec/VoidExpect: - Enabled: false -RSpec/Yield: - Enabled: false -Security/Open: - Enabled: false -Style/AccessModifierDeclarations: - Enabled: false -Style/AccessorGrouping: - Enabled: false -Style/AsciiComments: - Enabled: false -Style/BisectedAttrAccessor: - Enabled: false -Style/CaseLikeIf: - Enabled: false -Style/ClassEqualityComparison: - Enabled: false -Style/ColonMethodDefinition: - Enabled: false -Style/CombinableLoops: - Enabled: false -Style/CommentedKeyword: - Enabled: false -Style/Dir: - Enabled: false -Style/DoubleCopDisableDirective: - Enabled: false -Style/EmptyBlockParameter: - Enabled: false -Style/EmptyLambdaParameter: - Enabled: false -Style/Encoding: - Enabled: false -Style/EvalWithLocation: - Enabled: false -Style/ExpandPathArguments: - Enabled: false -Style/ExplicitBlockArgument: - Enabled: false -Style/ExponentialNotation: - Enabled: false -Style/FloatDivision: - Enabled: false -Style/FrozenStringLiteralComment: - Enabled: false -Style/GlobalStdStream: - Enabled: false -Style/HashAsLastArrayItem: - Enabled: false -Style/HashLikeCase: - Enabled: false -Style/HashTransformKeys: - Enabled: false -Style/HashTransformValues: - Enabled: false -Style/IfUnlessModifier: - Enabled: false -Style/KeywordParametersOrder: - Enabled: false -Style/MinMax: - Enabled: false + Description: A handful of these provider specs need one more `let` than the + default allows; restructuring them into fewer, larger fixtures would hurt + readability more than it helps. + Max: 6 Style/MixinUsage: - Enabled: false -Style/MultilineWhenThen: - Enabled: false -Style/NegatedUnless: - Enabled: false -Style/NumericPredicate: - Enabled: false -Style/OptionalBooleanParameter: - Enabled: false -Style/OrAssignment: - Enabled: false -Style/RandomWithOffset: - Enabled: false -Style/RedundantAssignment: - Enabled: false -Style/RedundantCondition: - Enabled: false -Style/RedundantConditional: - Enabled: false -Style/RedundantFetchBlock: - Enabled: false -Style/RedundantFileExtensionInRequire: - Enabled: false -Style/RedundantRegexpCharacterClass: - Enabled: false -Style/RedundantRegexpEscape: - Enabled: false -Style/RedundantSelfAssignment: - Enabled: false -Style/RedundantSort: - Enabled: false -Style/RescueStandardError: - Enabled: false -Style/SingleArgumentDig: - Enabled: false -Style/SlicingWithRange: - Enabled: false -Style/SoleNestedConditional: - Enabled: false -Style/StderrPuts: - Enabled: false -Style/StringConcatenation: - Enabled: false -Style/Strip: - Enabled: false -Style/SymbolProc: - Enabled: false -Style/TrailingBodyOnClass: - Enabled: false -Style/TrailingBodyOnMethodDefinition: - Enabled: false -Style/TrailingBodyOnModule: - Enabled: false -Style/TrailingCommaInHashLiteral: - Enabled: false -Style/TrailingMethodEndStatement: - Enabled: false -Style/UnpackFirst: - Enabled: false -Lint/DuplicateBranch: - Enabled: false -Lint/DuplicateRegexpCharacterClassElement: - Enabled: false -Lint/EmptyBlock: - Enabled: false -Lint/EmptyClass: - Enabled: false -Lint/NoReturnInBeginEndBlocks: - Enabled: false -Lint/ToEnumArguments: - Enabled: false -Lint/UnexpectedBlockArity: - Enabled: false -Lint/UnmodifiedReduceAccumulator: - Enabled: false -Performance/CollectionLiteralInLoop: - Enabled: false -Style/ArgumentsForwarding: - Enabled: false -Style/CollectionCompact: - Enabled: false -Style/DocumentDynamicEvalDefinition: - Enabled: false -Style/NegatedIfElseCondition: - Enabled: false -Style/NilLambda: - Enabled: false -Style/RedundantArgument: - Enabled: false -Style/SwapValues: - Enabled: false + Description: spec_helper.rb includes RspecPuppetFacts at the top level, which + is the standard convention across PDK/voxpupuli module spec_helpers. + Exclude: + - spec/spec_helper.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 72cb178..625a5a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [2.0.0] - 2026-07-21 +### Changed +- **BREAKING**: Replace Puppet 6/7 support with OpenVox 8; CI now runs on Ruby 3.2 and Ruby 4.0. The Gemfile now depends on the `openvox` gem (via `voxpupuli-test`) instead of `puppet`, and `PUPPET_VERSION` replaces `PUPPET_GEM_VERSION` +- **BREAKING**: Drop support for Windows 10, Windows Server 2012, and Windows Server 2012 R2 + +### Added +- Add support for Windows Server 2025 + ## [1.2.0] - 2026-07-16 - Add support for 'Domain controller' security options (Allow server operators to schedule tasks, Allow vulnerable Netlogon secure channel connections, LDAP server channel binding token requirements, LDAP server signing requirements, Refuse machine account password changes) diff --git a/Gemfile b/Gemfile index 1589fee..2bb3376 100644 --- a/Gemfile +++ b/Gemfile @@ -13,23 +13,11 @@ def location_for(place_or_version, fake_version = nil) end end -ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments -minor_version = ruby_version_segments[0..1].join('.') - group :development do - gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 2.8.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) - gem "puppet-module-posix-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] - gem "puppet-module-posix-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] - gem "puppet-module-win-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-win-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "voxpupuli-puppet-lint-plugins", '>= 3.0', require: false - gem "pry-byebug", require: false -end -group :system_tests do - gem "puppet-module-posix-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] - gem "puppet-module-win-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "voxpupuli-test", '~> 14.0', require: false + gem "rubocop-performance", '~> 1.26', require: false + gem "awesome_print", require: false + gem "pry-byebug", require: false end group :acceptance do gem "beaker", require: false @@ -45,13 +33,13 @@ group :acceptance do gem "bcrypt_pbkdf", require: false end -puppet_version = ENV['PUPPET_GEM_VERSION'] +puppet_version = ENV['PUPPET_VERSION'] || '~> 8.0' facter_version = ENV['FACTER_GEM_VERSION'] hiera_version = ENV['HIERA_GEM_VERSION'] gems = {} -gems['puppet'] = location_for(puppet_version) +gems['openvox'] = location_for(puppet_version) # If facter or hiera versions have been specified via the environment # variables diff --git a/Rakefile b/Rakefile index 0f8754e..a1f2096 100644 --- a/Rakefile +++ b/Rakefile @@ -2,8 +2,12 @@ require 'bundler' require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? -require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-syntax/tasks/puppet-syntax' +begin + require 'voxpupuli/test/rake' +rescue LoadError + require 'puppetlabs_spec_helper/rake_tasks' + require 'puppet-syntax/tasks/puppet-syntax' +end require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? diff --git a/lib/puppet/provider/local_security_policy/policy.rb b/lib/puppet/provider/local_security_policy/policy.rb index 2433ace..8741683 100644 --- a/lib/puppet/provider/local_security_policy/policy.rb +++ b/lib/puppet/provider/local_security_policy/policy.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # frozen_string_literal: true require 'fileutils' @@ -6,7 +5,7 @@ begin require 'puppet_x/twp/inifile' require 'puppet_x/lsp/security_policy' -rescue LoadError => _detail +rescue LoadError => _e require 'pathname' # JJM WORK_AROUND #14073 mod = Puppet::Module.find('local_security_policy', Puppet[:environment].to_s) if mod @@ -64,9 +63,8 @@ def self.fixup_value(value, type) when :quoted_string value = "\"#{value}\"" when :principal - sids = Array.[] - value.split(',').each do |suser| - sids << ((suser !~ %r{^(\*S-1-.+)$}) ? ('*' + Puppet::Util::Windows::SID.name_to_sid(suser).to_s) : suser.to_s) + sids = value.split(',').map do |suser| + (suser =~ %r{^(\*S-1-.+)$}) ? suser.to_s : ("*#{Puppet::Util::Windows::SID.name_to_sid(suser)}") end value = sids.sort.join(',') end @@ -85,6 +83,7 @@ def self.instances inf.each do |section, parameter_name, parameter_value| next if section == 'Unicode' next if section == 'Version' + begin ensure_value = parameter_value.nil? ? :absent : :present policy_desc, policy_values = SecurityPolicy.find_mapping_from_policy_name(parameter_name) @@ -119,7 +118,7 @@ def flush end def initialize(value = {}) - super(value) + super @property_flush = {} end diff --git a/lib/puppet/type/local_security_policy.rb b/lib/puppet/type/local_security_policy.rb index ab97ee6..4dccff6 100644 --- a/lib/puppet/type/local_security_policy.rb +++ b/lib/puppet/type/local_security_policy.rb @@ -2,7 +2,7 @@ begin require 'puppet_x/lsp/security_policy' -rescue LoadError => _detail +rescue LoadError => _e require 'pathname' # JJM WORK_AROUND #14073 mod = Puppet::Module.find('local_security_policy', Puppet[:environment].to_s) if mod @@ -100,9 +100,7 @@ # REG_DWORD 4 when '4' test_val = value.to_i - if test_val < -2_147_483_648 || test_val > 2_147_483_647 - raise ArgumentError, "Invalid value for type: #{test_val} for REG_DWORD" - end + raise ArgumentError, "Invalid value for type: #{test_val} for REG_DWORD" if test_val < -2_147_483_648 || test_val > 2_147_483_647 # REG_DWORD_LITTLE_ENDIAN 4 # REG_DWORD_BIG_ENDIAN 5 # REG_LINK 6 @@ -115,9 +113,7 @@ # REG_QWORD 11 when '11' test_val = value.to_i - if test_val < -9_223_372_036_854_775_808 || test_val > 9_223_372_036_854_775_807 - raise ArgumentError, "Invalid value for type: #{test_val} for REG_QWORD" - end + raise ArgumentError, "Invalid value for type: #{test_val} for REG_QWORD" if test_val < -9_223_372_036_854_775_808 || test_val > 9_223_372_036_854_775_807 # REG_QWORD_LITTLE_ENDIAN 11 end when 'System Access' diff --git a/lib/puppet_x/lsp/security_policy.rb b/lib/puppet_x/lsp/security_policy.rb index 6ed52e4..e75e277 100644 --- a/lib/puppet_x/lsp/security_policy.rb +++ b/lib/puppet_x/lsp/security_policy.rb @@ -9,8 +9,6 @@ class SecurityPolicy EVENT_TYPES = ['Success,Failure', 'Success', 'Failure', 'No auditing', 0, 1, 2, 3].freeze REGISTRY_TYPES = [1, 3, 4, 7].freeze - def initialize; end - def user_to_sid(value) if value.match?(%r{^\*}) result = value @@ -19,7 +17,7 @@ def user_to_sid(value) if user_sid.nil? warn("\"#{value}\" does not exist") else - result = '*' + user_sid + result = "*#{user_sid}" end end result @@ -104,9 +102,8 @@ def self.find_mapping_from_policy_name(name) key, value = lsp_mapping.find do |_key, hash| hash[:name] == name end - unless key && value - raise KeyError, "#{name} is not a valid policy" - end + raise KeyError, "#{name} is not a valid policy" unless key && value + [key, value] end @@ -116,9 +113,8 @@ def self.find_mapping_from_policy_desc(desc) _key, value = lsp_mapping.find do |key, _hash| key.downcase == name end - unless value - raise KeyError, "#{desc} is not a valid policy" - end + raise KeyError, "#{desc} is not a valid policy" unless value + value end @@ -129,6 +125,7 @@ def self.valid_lsp?(name) def self.convert_registry_value(name, value) value = value.to_s return value if value.split(',').count > 1 && REGISTRY_TYPES.include?(value.split(',')[0].to_i) + policy_hash = find_mapping_from_policy_desc(name) "#{policy_hash[:reg_type]},#{value}" end diff --git a/lib/puppet_x/twp/inifile.rb b/lib/puppet_x/twp/inifile.rb index 85f1c81..3ff221f 100644 --- a/lib/puppet_x/twp/inifile.rb +++ b/lib/puppet_x/twp/inifile.rb @@ -1,9 +1,8 @@ -# encoding: UTF-8 # frozen_string_literal: true # This class represents the INI file and can be used to parse, modify, # and write INI files. -module PuppetX # rubocop:disable Style/ClassAndModuleChildren +module PuppetX # class IniFile class IniFile include Enumerable @@ -31,6 +30,7 @@ class Error < StandardError; end # Returns an IniFile instance or nil if the file could not be opened. def self.load(filename, opts = {}) return unless File.file? filename + new(opts.merge(filename: filename)) end @@ -126,6 +126,7 @@ def read(opts = {}) filename = opts.fetch(:filename, @filename) encoding = opts.fetch(:encoding, @encoding) return unless File.file? filename + mode = encoding ? "r:#{encoding}" : 'r' File.open(filename, mode) { |fd| parse fd } @@ -219,6 +220,7 @@ def merge!(other) # Returns this IniFile. def each return unless block_given? + @ini.each do |section, hash| hash.each do |param, val| yield section, param, val @@ -239,9 +241,10 @@ def each # end # # Returns this IniFile. - def each_section + def each_section(&) return unless block_given? - @ini.each_key { |section| yield section } + + @ini.each_key(&) self end @@ -267,6 +270,7 @@ def delete_section(section) # Returns the Hash of parameter/value pairs for this section. def [](section) return nil if section.nil? + @ini[section.to_s] end @@ -306,7 +310,7 @@ def match(regex) # section - The section name as a String. # # Returns true if the section exists in the IniFile. - def has_section?(section) # rubocop:disable Style/PredicateName + def has_section?(section) # rubocop:disable Naming/PredicatePrefix @ini.key? section.to_s end @@ -321,7 +325,7 @@ def sections # Returns this IniFile. def freeze super - @ini.each_value { |h| h.freeze } + @ini.each_value(&:freeze) @ini.freeze self end @@ -332,7 +336,7 @@ def freeze # Returns this IniFile. def taint super - @ini.each_value { |h| h.taint } + @ini.each_value(&:taint) @ini.taint self end @@ -372,6 +376,7 @@ def clone def eql?(other) return true if equal? other return false unless other.instance_of? self.class + @ini == other.instance_variable_get(:@ini) end alias == eql? @@ -410,8 +415,7 @@ def parse(content) # object. class Parser attr_writer :section - attr_accessor :property - attr_accessor :value + attr_accessor :property, :value # Create a new IniFile::Parser that can be used to parse the contents of # an .ini file. @@ -602,10 +606,10 @@ def typecast(value) begin begin Integer(value) - rescue + rescue StandardError Float(value) end - rescue + rescue StandardError unescape_value(value) end end @@ -621,7 +625,7 @@ def typecast(value) def unescape_value(value) value = value.to_s value.gsub!(%r{\\[0nrt\\]}) do |char| - case char + case char # rubocop:disable Style/HashLikeCase -- leave as-is, this is vendored escape-parsing logic when '\0' then "\0" when '\n' then "\n" when '\r' then "\r" diff --git a/metadata.json b/metadata.json index eed74e4..e42ccfa 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "ayohrling-local_security_policy", - "version": "1.2.0", + "version": "2.0.0", "author": "Paul S. Cannon, Adam Yohrling, Corey Osman, Ryan Russell-Yates, Jordan Wesolowski, Gerben Welter, Thomas Linkin, Andy Adrian, Steven Pritchard", "summary": "Windows Local Security Policy management. Forked from cannonps/local_security_policy", "license": "Apache-2.0", @@ -14,19 +14,17 @@ { "operatingsystem": "windows", "operatingsystemrelease": [ - "10", - "2012", - "2012 R2", "2016", "2019", - "2022" + "2022", + "2025" ] } ], "requirements": [ { - "name": "puppet", - "version_requirement": ">= 6.0.0 < 8.0.0" + "name": "openvox", + "version_requirement": ">= 8.0.0 < 9.0.0" } ], "tags": [ diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml index 25c4f16..2d64e7c 100644 --- a/spec/acceptance/nodesets/default.yml +++ b/spec/acceptance/nodesets/default.yml @@ -22,4 +22,4 @@ HOSTS: CONFIG: log_level: verbose type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'openvox8' %> diff --git a/spec/acceptance/nodesets/win2012r2.yml b/spec/acceptance/nodesets/win2012r2.yml deleted file mode 100644 index 3b06e4e..0000000 --- a/spec/acceptance/nodesets/win2012r2.yml +++ /dev/null @@ -1,27 +0,0 @@ -<% - if ENV['BEAKER_HYPERVISOR'] - hypervisor = ENV['BEAKER_HYPERVISOR'] - else - hypervisor = 'vagrant' - end --%> ---- -HOSTS: - win2012r2: - roles: - - default - - windows - platform: windows-server-amd64 - box: devopsgroup-io/windows_server-2012r2-standard-amd64-nocm - hypervisor: <%= hypervisor %> - vagrant_memsize: 2048 - vagrant_cpus: 2 - user: vagrant - is_cygwin: false - ssh: - append_all_supported_algorithms: true - -CONFIG: - log_level: verbose - type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> diff --git a/spec/acceptance/nodesets/win2016.yml b/spec/acceptance/nodesets/win2016.yml index c3da773..8bb699e 100644 --- a/spec/acceptance/nodesets/win2016.yml +++ b/spec/acceptance/nodesets/win2016.yml @@ -22,4 +22,4 @@ HOSTS: CONFIG: log_level: verbose type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'openvox8' %> diff --git a/spec/acceptance/nodesets/win2019.yml b/spec/acceptance/nodesets/win2019.yml index f775d33..2d3dda8 100644 --- a/spec/acceptance/nodesets/win2019.yml +++ b/spec/acceptance/nodesets/win2019.yml @@ -23,4 +23,4 @@ HOSTS: CONFIG: log_level: verbose type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'openvox8' %> diff --git a/spec/acceptance/nodesets/win2022.yml b/spec/acceptance/nodesets/win2022.yml index 19b5084..c8d5e18 100644 --- a/spec/acceptance/nodesets/win2022.yml +++ b/spec/acceptance/nodesets/win2022.yml @@ -23,4 +23,4 @@ HOSTS: CONFIG: log_level: verbose type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'openvox8' %> diff --git a/spec/acceptance/nodesets/win10.yml b/spec/acceptance/nodesets/win2025.yml similarity index 70% rename from spec/acceptance/nodesets/win10.yml rename to spec/acceptance/nodesets/win2025.yml index 2318159..d5492e7 100644 --- a/spec/acceptance/nodesets/win10.yml +++ b/spec/acceptance/nodesets/win2025.yml @@ -7,12 +7,13 @@ -%> --- HOSTS: - win10: + win2025: roles: - default - windows platform: windows-server-amd64 - box: gusztavvargadr/windows-10 + box: 'gusztavvargadr/windows-server' + box_version: '~> 2503' hypervisor: <%= hypervisor %> vagrant_memsize: 2048 vagrant_cpus: 2 @@ -22,4 +23,4 @@ HOSTS: CONFIG: log_level: verbose type: aio - puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'puppet7' %> + puppet_collection: <%= ENV['BEAKER_PUPPET_COLLECTION'] || 'openvox8' %> diff --git a/spec/acceptance/suites/01_system_access_spec.rb b/spec/acceptance/suites/01_system_access_spec.rb index 43291bf..18b02bb 100644 --- a/spec/acceptance/suites/01_system_access_spec.rb +++ b/spec/acceptance/suites/01_system_access_spec.rb @@ -33,10 +33,10 @@ context 'rename guest account' do let(:manifest) do <<~END - local_security_policy { 'Accounts: Rename guest account': - ensure => present, - policy_value => '"lsp_guest"', - } + local_security_policy { 'Accounts: Rename guest account': + ensure => present, + policy_value => '"lsp_guest"', + } END end @@ -50,10 +50,10 @@ context 'rename administrator account' do let(:manifest) do <<~END - local_security_policy { 'Accounts: Rename administrator account': - ensure => present, - policy_value => '"lsp_admin"', - } + local_security_policy { 'Accounts: Rename administrator account': + ensure => present, + policy_value => '"lsp_admin"', + } END end diff --git a/spec/acceptance/suites/04_registry_values_spec.rb b/spec/acceptance/suites/04_registry_values_spec.rb index 52dc824..fdcc580 100644 --- a/spec/acceptance/suites/04_registry_values_spec.rb +++ b/spec/acceptance/suites/04_registry_values_spec.rb @@ -5,7 +5,7 @@ def get_reg_key_on(host, key) powershell = 'powershell.exe -noprofile -nologo -noninteractive -command' - ps = on host, %(#{powershell} "Get-ItemProperty -Path \\\"#{key}\\\" | ConvertTo-Json") + ps = on host, %(#{powershell} "Get-ItemProperty -Path \\"#{key}\\" | ConvertTo-Json") JSON.parse(ps.stdout) end @@ -13,10 +13,10 @@ def get_reg_key_on(host, key) context 'enable registry value policy' do let(:manifest) do <<~END - local_security_policy { 'Network access: Restrict clients allowed to make remote calls to SAM': - ensure => present, - policy_value => '1,"O:BAG:BAD:(A;;RC;;;BA)"', - } + local_security_policy { 'Network access: Restrict clients allowed to make remote calls to SAM': + ensure => present, + policy_value => '1,"O:BAG:BAD:(A;;RC;;;BA)"', + } END end @@ -37,10 +37,10 @@ def get_reg_key_on(host, key) context 'disable registry value policy' do let(:manifest) do <<~END - local_security_policy { 'Network access: Restrict clients allowed to make remote calls to SAM': - ensure => present, - policy_value => '', - } + local_security_policy { 'Network access: Restrict clients allowed to make remote calls to SAM': + ensure => present, + policy_value => '', + } END end diff --git a/spec/acceptance/suites/99_hiera_spec.rb b/spec/acceptance/suites/99_hiera_spec.rb index 85fd2f3..793afdb 100644 --- a/spec/acceptance/suites/99_hiera_spec.rb +++ b/spec/acceptance/suites/99_hiera_spec.rb @@ -29,9 +29,7 @@ hosts.each do |host| value = on(host, 'type C:\secedit.txt') expect(value.output).to match(%r{^PasswordHistorySize\s*=\s*30$}) - end - hosts.each do |host| value = on(host, 'auditpol /get /category:*') expect(value.output).to match(%r{^\s*Credential Validation\s*Success$}) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 08d5fb8..3d8a8fc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,9 +4,28 @@ c.mock_with :rspec end -require 'puppetlabs_spec_helper/module_spec_helper' +require 'voxpupuli/test/spec_helper' require 'rspec-puppet-facts' +# puppetlabs_spec_helper provided this; voxpupuli-test does not, so shim it +# to keep `include PuppetlabsSpec::Fixtures` / `my_fixture` working in specs. +module PuppetlabsSpec + module Fixtures + def my_fixture_dir + callers = caller + path = callers.find { |c| c =~ %r{_spec\.rb} } + raise "my_fixture/my_fixture_dir must be called from a *_spec.rb file; no such frame was found in the call stack: #{callers.first(5).join(', ')}" unless path + + path = path.split(%r{:\d+}).first + path.sub(%r{spec/(?!fixtures)}, 'spec/fixtures/').sub(%r{_spec\.rb$}, '') + end + + def my_fixture(file) + File.join(my_fixture_dir, file) + end + end +end + require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) include RspecPuppetFacts @@ -25,8 +44,8 @@ next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin - default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) - rescue => e + default_facts.merge!(YAML.safe_load_file(f, permitted_classes: [], permitted_symbols: [], aliases: true)) + rescue StandardError => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end end @@ -46,8 +65,6 @@ Puppet.settings[:strict_variables] = true end c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] - c.after(:suite) do - end # Filter backtrace noise backtrace_exclusion_patterns = [ diff --git a/spec/unit/puppet/provider/local_security_policy/policy_spec.rb b/spec/unit/puppet/provider/local_security_policy/policy_spec.rb index 07c4a41..ed054b6 100644 --- a/spec/unit/puppet/provider/local_security_policy/policy_spec.rb +++ b/spec/unit/puppet/provider/local_security_policy/policy_spec.rb @@ -3,27 +3,24 @@ require 'spec_helper' require 'awesome_print' -provider_class = Puppet::Type.type(:local_security_policy).provider(:policy) - -# rubocop:disable RSpec/SubjectStub,RSpec/NamedSubject -describe provider_class do +# rubocop:disable RSpec/SubjectStub +describe Puppet::Type.type(:local_security_policy).provider(:policy) do include PuppetlabsSpec::Fixtures - subject { provider_class } + subject { described_class } before(:each) do allow(Puppet::Util).to receive(:which).with('secedit').and_return('c:\\tools\\secedit') infout = StringIO.new sdbout = StringIO.new - allow(provider_class).to receive(:read_policy_settings).and_return(inf_data) - allow(subject).to receive(:read_policy_settings).and_return(inf_data) + allow(described_class).to receive(:read_policy_settings).and_return(inf_data) allow(Tempfile).to receive(:new).with('infimport').and_return(infout) allow(Tempfile).to receive(:new).with('sdbimport').and_return(sdbout) allow(File).to receive(:file?).with(secdata).and_return(true) # the below mock seems to be required or rspec complains allow(File).to receive(:file?).with(%r{facter|lsb_release}).and_return(true) - allow(subject).to receive(:temp_file).and_return(secdata) + allow(subject).to receive_messages(read_policy_settings: inf_data, temp_file: secdata) allow(subject).to receive(:secedit).with(['/configure', '/db', 'sdbout', '/cfg', 'infout', '/quiet']).and_return(true) allow(subject).to receive(:secedit).with(['/export', '/cfg', secdata, '/quiet']).and_return(true) end @@ -53,11 +50,11 @@ ) end let(:provider) do - provider_class.new(resource) + described_class.new(resource) end it 'creates instances without error' do - instances = provider_class.instances + instances = described_class.instances expect(instances.class).to eq(Array) expect(instances.count).to be >= 114 end @@ -71,25 +68,25 @@ inffile.sections.each do |section| next if section == 'Unicode' next if section == 'Version' + inffile[section].each do |name, value| - begin - SecurityPolicy.find_mapping_from_policy_name(name) - rescue KeyError => e - puts e.message - if value && section == 'Registry Values' - reg_type = value.split(',').first - missing_policies[name] = { name: name, policy_type: section, reg_type: reg_type } - else - missing_policies[name] = { name: name, policy_type: section } - end + SecurityPolicy.find_mapping_from_policy_name(name) + rescue KeyError => e + puts e.message # rubocop:disable RSpec/Output -- diagnostic output for maintainers when this test fails, see comment above + if value && section == 'Registry Values' + reg_type = value.split(',').first + missing_policies[name] = { name: name, policy_type: section, reg_type: reg_type } + else + missing_policies[name] = { name: name, policy_type: section } end end end - ap missing_policies + ap missing_policies # rubocop:disable RSpec/Output -- diagnostic output for maintainers when this test fails, see comment above + expect(missing_policies.count).to eq(0), 'Missing policy, check the lsp mapping' end - xit 'ensure instances works' do + it 'ensure instances works', skip: 'Puppet::Type.type(...).instances goes through provider suitability confinement (confine operatingsystem: :windows), so it returns 0 instances on this non-Windows test host' do instances = Puppet::Type.type(:local_security_policy).instances expect(instances.count).to be > 1 end @@ -122,7 +119,7 @@ end it 'exists? is true' do - expect(provider.exists?).to eq(false) + expect(provider.exists?).to be(false) # until we can implement the destroy functionality this test is useless # expect(provider).to receive(:destroy).exactly(1).times end @@ -159,8 +156,8 @@ end it 'exists? is false' do - expect(provider.exists?).to eq(false) - allow(provider).to receive(:create).exactly(1).times + expect(provider.exists?).to be(false) + allow(provider).to receive(:create).once end end @@ -168,3 +165,4 @@ expect(provider).to be_an_instance_of Puppet::Type::Local_security_policy::ProviderPolicy end end +# rubocop:enable RSpec/SubjectStub diff --git a/spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb b/spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb index 68f1e41..8f3c6f6 100644 --- a/spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb +++ b/spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb @@ -4,7 +4,7 @@ require 'puppet_x/lsp/security_policy' require 'puppet/util' -# rubocop:disable RSpec/SubjectStub,RSpec/NamedSubject +# rubocop:disable RSpec/SubjectStub describe 'SecurityPolicy' do include PuppetlabsSpec::Fixtures @@ -48,8 +48,7 @@ SecurityPolicy.new end - # sid_to_user function is not used anywhere, no need to test... - xit 'returns user' do + it 'returns user', skip: 'sid_to_user function is not used anywhere, no need to test' do expect(security_policy.sid_to_user('S-1-5-32-556')).to eq('Network Configuration Operators') expect(security_policy.sid_to_user('*S-1-5-80-0')).to eq('NT_SERVICE\\ALL_SERVICES') end @@ -64,7 +63,7 @@ end it 'returns nil when sid is not found' do - expect(security_policy.user_to_sid('N_SERVICE\\ALL_SERVICES')).to eq(nil) + expect(security_policy.user_to_sid('N_SERVICE\\ALL_SERVICES')).to be_nil end describe 'registry value' do @@ -173,3 +172,4 @@ # end # end end +# rubocop:enable RSpec/SubjectStub