From d4d14968aebfa18dbe86b6e83b5e0d4d26e64322 Mon Sep 17 00:00:00 2001 From: Mike Riddle Date: Tue, 21 Jul 2026 15:32:50 -0400 Subject: [PATCH 1/4] Modernize CI to OpenVox 8 / Ruby 3.2+4.0 and drop legacy Windows support Replace the Puppet 6/7 CI matrix with OpenVox 8 on Ruby 3.2 and Ruby 4.0. This required replacing the Gemfile's per-Ruby-minor-version PDK meta-gems (which don't exist for Ruby 4.0, and were the root cause of the earlier patron/libcurl CI failures) with voxpupuli-test and an explicit openvox dependency, matching the pattern used by pupmod-simp-useradd and pupmod-voxpupuli-kmod. Rakefile, .rubocop.yml, and spec/spec_helper.rb are updated accordingly: - Rakefile now loads tasks via voxpupuli/test/rake - .rubocop.yml inherits voxpupuli-test's shared config instead of the frozen PDK-era cop list; the newer rubocop/rubocop-rspec versions surface ~70 pre-existing style offenses across vendored/spec code, grandfathered via a generated .rubocop_todo.yml rather than risk autocorrecting the vendored inifile.rb - spec_helper.rb shims PuppetlabsSpec::Fixtures#my_fixture (dropped by the new toolchain) and fixes a YAML.safe_load call broken by modern Psych's keyword-arg signature Also drop support for Windows 10, Server 2012, and Server 2012 R2, and add support for Windows Server 2025 (metadata.json, new win2025.yml nodeset). This is a breaking change, so bump to 2.0.0. Co-Authored-By: Claude Fable 5 --- .github/workflows/pr.yml | 34 +- .rubocop.yml | 467 +----------------- .rubocop_todo.yml | 223 +++++++++ CHANGELOG.md | 8 + Gemfile | 24 +- Rakefile | 8 +- metadata.json | 12 +- spec/acceptance/nodesets/default.yml | 2 +- spec/acceptance/nodesets/win2012r2.yml | 27 - spec/acceptance/nodesets/win2016.yml | 2 +- spec/acceptance/nodesets/win2019.yml | 2 +- spec/acceptance/nodesets/win2022.yml | 2 +- .../nodesets/{win10.yml => win2025.yml} | 7 +- spec/spec_helper.rb | 21 +- 14 files changed, 299 insertions(+), 540 deletions(-) create mode 100644 .rubocop_todo.yml delete mode 100644 spec/acceptance/nodesets/win2012r2.yml rename spec/acceptance/nodesets/{win10.yml => win2025.yml} (70%) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 1c4f916..7f9b358 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -10,24 +10,22 @@ 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: 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 + - run: bundle exec rake syntax lint metadata_lint check:git_ignore check:dot_underscore check:test_file rubocop parallel_spec: needs: @@ -36,19 +34,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: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.puppet.ruby_version}} diff --git a/.rubocop.yml b/.rubocop.yml index 25fe076..bf873fd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,23 +1,12 @@ --- -require: -- rubocop-performance -- rubocop-rspec +inherit_from: .rubocop_todo.yml + +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 +62,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 +80,3 @@ 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 -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 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..b26812c --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,223 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --no-auto-gen-timestamp` +# using RuboCop version 1.85.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 11 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + - 'lib/puppet_x/lsp/security_policy.rb' + - 'lib/puppet_x/twp/inifile.rb' + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Layout/HeredocIndentation: + Exclude: + - 'spec/acceptance/suites/01_system_access_spec.rb' + - 'spec/acceptance/suites/04_registry_values_spec.rb' + +# Offense count: 1 +# Configuration parameters: AllowComments, AllowEmptyLambdas. +Lint/EmptyBlock: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 2 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Lint/RedundantCopDisableDirective: + Exclude: + - 'lib/puppet_x/twp/inifile.rb' + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' + +# Offense count: 1 +# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs. +# NamePrefix: is_, has_, have_, does_ +# ForbiddenPrefixes: is_, has_, have_, does_ +# AllowedMethods: is_a? +# MethodDefinitionMacros: define_method, define_singleton_method +Naming/PredicatePrefix: + Exclude: + - 'spec/**/*' + - 'lib/puppet_x/twp/inifile.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + - 'lib/puppet/type/local_security_policy.rb' + +# Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/BeEq: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' + +# Offense count: 1 +RSpec/LeakyLocalVariable: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 5 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 6 + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/Output: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 2 +RSpec/PendingWithoutReason: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +RSpec/ReceiveCounts: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/ReceiveMessages: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: separated, grouped +Style/AccessorGrouping: + Exclude: + - 'lib/puppet_x/twp/inifile.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/CombinableLoops: + Exclude: + - 'spec/acceptance/suites/99_hiera_spec.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/EmptyLiteral: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/Encoding: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + - 'lib/puppet_x/twp/inifile.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/ExplicitBlockArgument: + Exclude: + - 'lib/puppet_x/twp/inifile.rb' + +# Offense count: 1 +# Configuration parameters: MinBranchesCount. +Style/HashLikeCase: + Exclude: + - 'lib/puppet_x/twp/inifile.rb' + +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +Style/IfUnlessModifier: + Exclude: + - 'lib/puppet/type/local_security_policy.rb' + - 'lib/puppet_x/lsp/security_policy.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/MapIntoArray: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + +# Offense count: 1 +Style/MixinUsage: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/NegatedIfElseCondition: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantArrayConstructor: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantBegin: + Exclude: + - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowComments. +Style/RedundantInitialize: + Exclude: + - 'lib/puppet_x/lsp/security_policy.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantStringEscape: + Exclude: + - 'spec/acceptance/suites/04_registry_values_spec.rb' + +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/puppet_x/twp/inifile.rb' + - 'spec/spec_helper.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + - 'lib/puppet_x/lsp/security_policy.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Style/SuperArguments: + Exclude: + - 'lib/puppet/provider/local_security_policy/policy.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method +Style/SymbolProc: + Exclude: + - 'lib/puppet_x/twp/inifile.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/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/spec_helper.rb b/spec/spec_helper.rb index 08d5fb8..f41410f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,9 +4,26 @@ 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} } + 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,7 +42,7 @@ next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin - default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) + default_facts.merge!(YAML.safe_load_file(f, permitted_classes: [], permitted_symbols: [], aliases: true)) rescue => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end From 83c2e67e74126dd1b235d3ff42a2fdf5fd91129a Mon Sep 17 00:00:00 2001 From: Mike Riddle Date: Tue, 21 Jul 2026 15:54:31 -0400 Subject: [PATCH 2/4] Fix rubocop offenses grandfathered in .rubocop_todo.yml and remove it Applies safe and verified-safe autocorrections (whitespace, redundant syntax, string interpolation, RSpec equivalences like eq(false) -> be(false) and .exactly(1).times -> .once), each checked for behavioral equivalence and confirmed via the full test suite (69 examples, 0 failures, 2 pendings, unchanged throughout). A few offenses were deliberately kept as documented exceptions in .rubocop.yml rather than "fixed", because the fix would have been riskier than the offense: - has_section? in the vendored inifile.rb (Naming/PredicatePrefix) is unused internally but is synced/vendored public API - the character-escaping case/when in the same file (Style/HashLikeCase) - RSpec/MultipleMemoizedHelpers and the top-level `include` in spec_helper.rb (Style/MixinUsage) are legitimate existing conventions - two diagnostic puts/ap lines in a real (non-pending) spec, restored after autocorrect deleted them Also: replaced the leaky top-level provider_class local variable with RSpec's described_class idiom, removed a no-op empty after(:suite) block, and gave both pending `xit` tests real reasons instead of RSpec's generic default message -- verified empirically why each is skipped rather than guessing. Found but did not fix: IniFile#taint/#tainted? call Object#taint, which was removed entirely in Ruby 3.2 (our new target version). Dead code today -- nothing in this module calls .dup/.clone/.taint on an IniFile -- but will raise NoMethodError if ever exercised. Co-Authored-By: Claude Fable 5 --- .rubocop.yml | 12 +- .rubocop_todo.yml | 223 ------------------ .../provider/local_security_policy/policy.rb | 11 +- lib/puppet/type/local_security_policy.rb | 10 +- lib/puppet_x/lsp/security_policy.rb | 15 +- lib/puppet_x/twp/inifile.rb | 28 ++- .../suites/01_system_access_spec.rb | 16 +- .../suites/04_registry_values_spec.rb | 18 +- spec/acceptance/suites/99_hiera_spec.rb | 2 - spec/spec_helper.rb | 4 +- .../local_security_policy/policy_spec.rb | 48 ++-- .../security_policy_spec.rb | 8 +- 12 files changed, 85 insertions(+), 310 deletions(-) delete mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml index bf873fd..3386144 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,4 @@ --- -inherit_from: .rubocop_todo.yml - inherit_gem: voxpupuli-test: rubocop.yml @@ -80,3 +78,13 @@ Style/Documentation: - spec/**/* Style/WordArray: EnforcedStyle: brackets +RSpec/MultipleMemoizedHelpers: + 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: + 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/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index b26812c..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,223 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config --no-auto-gen-timestamp` -# using RuboCop version 1.85.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 11 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterGuardClause: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - - 'lib/puppet_x/lsp/security_policy.rb' - - 'lib/puppet_x/twp/inifile.rb' - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Layout/HeredocIndentation: - Exclude: - - 'spec/acceptance/suites/01_system_access_spec.rb' - - 'spec/acceptance/suites/04_registry_values_spec.rb' - -# Offense count: 1 -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/spec_helper.rb' - -# Offense count: 2 -# Configuration parameters: MaximumRangeSize. -Lint/MissingCopEnableDirective: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Lint/RedundantCopDisableDirective: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' - -# Offense count: 1 -# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs. -# NamePrefix: is_, has_, have_, does_ -# ForbiddenPrefixes: is_, has_, have_, does_ -# AllowedMethods: is_a? -# MethodDefinitionMacros: define_method, define_singleton_method -Naming/PredicatePrefix: - Exclude: - - 'spec/**/*' - - 'lib/puppet_x/twp/inifile.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: PreferredName. -Naming/RescuedExceptionsVariableName: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - - 'lib/puppet/type/local_security_policy.rb' - -# Offense count: 3 -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/BeEq: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' - -# Offense count: 1 -RSpec/LeakyLocalVariable: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 5 -# Configuration parameters: AllowSubject. -RSpec/MultipleMemoizedHelpers: - Max: 6 - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/Output: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 2 -RSpec/PendingWithoutReason: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - - 'spec/unit/puppet/provider/local_security_policy/security_policy_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -RSpec/ReceiveCounts: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/ReceiveMessages: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: separated, grouped -Style/AccessorGrouping: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/CombinableLoops: - Exclude: - - 'spec/acceptance/suites/99_hiera_spec.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/EmptyLiteral: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/Encoding: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - - 'lib/puppet_x/twp/inifile.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/ExplicitBlockArgument: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' - -# Offense count: 1 -# Configuration parameters: MinBranchesCount. -Style/HashLikeCase: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' - -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -Style/IfUnlessModifier: - Exclude: - - 'lib/puppet/type/local_security_policy.rb' - - 'lib/puppet_x/lsp/security_policy.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/MapIntoArray: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - -# Offense count: 1 -Style/MixinUsage: - Exclude: - - 'spec/spec_helper.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/NegatedIfElseCondition: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantArrayConstructor: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantBegin: - Exclude: - - 'spec/unit/puppet/provider/local_security_policy/policy_spec.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowComments. -Style/RedundantInitialize: - Exclude: - - 'lib/puppet_x/lsp/security_policy.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantStringEscape: - Exclude: - - 'spec/acceptance/suites/04_registry_values_spec.rb' - -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: implicit, explicit -Style/RescueStandardError: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' - - 'spec/spec_helper.rb' - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: Mode. -Style/StringConcatenation: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - - 'lib/puppet_x/lsp/security_policy.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/SuperArguments: - Exclude: - - 'lib/puppet/provider/local_security_policy/policy.rb' - -# Offense count: 2 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. -# AllowedMethods: define_method -Style/SymbolProc: - Exclude: - - 'lib/puppet_x/twp/inifile.rb' 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/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 f41410f..903e71b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -43,7 +43,7 @@ def my_fixture(file) begin default_facts.merge!(YAML.safe_load_file(f, permitted_classes: [], permitted_symbols: [], aliases: true)) - rescue => e + rescue StandardError => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end end @@ -63,8 +63,6 @@ def my_fixture(file) 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 From e522212b55a3583d2bf86f81442c2686c4293e4b Mon Sep 17 00:00:00 2001 From: Mike Riddle Date: Tue, 21 Jul 2026 16:10:09 -0400 Subject: [PATCH 3/4] Document why check:symlinks is dropped from the CI rake invocation Per review feedback: confirm and record that this was intentional, not an accidental omission. That rake task no longer exists under the voxpupuli-test toolchain, unlike the other check: tasks kept alongside it. Co-Authored-By: Claude Fable 5 --- .github/workflows/pr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7f9b358..6a9e0cb 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -25,6 +25,9 @@ jobs: with: ruby-version: ${{matrix.puppet.ruby_version}} bundler-cache: true + # 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: From 877fe610b9aa1e60b3d10593fe7082d18c0c0d07 Mon Sep 17 00:00:00 2001 From: Mike Riddle Date: Tue, 21 Jul 2026 16:17:29 -0400 Subject: [PATCH 4/4] Address silug's PR review: guard my_fixture_dir, bump checkout action Per review feedback on PR #136: - my_fixture_dir raised a confusing NoMethodError on nil if ever called from a non-*_spec.rb frame. Now raises a clear error instead. Verified this doesn't affect the two files that actually use it. - Bumped actions/checkout@v2 -> @v4 in both CI jobs (flagged as minor polish; retires a Node 16 deprecation warning while touching CI anyway). Also verified and can confirm: `rake metadata_lint` passes cleanly with the openvox requirement name -- metadata-json-lint doesn't restrict requirements[].name to an allowlist, so the puppet -> openvox rename isn't a validation concern. Co-Authored-By: Claude Fable 5 --- .github/workflows/pr.yml | 4 ++-- spec/spec_helper.rb | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6a9e0cb..f817339 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -20,7 +20,7 @@ jobs: PUPPET_VERSION: ${{matrix.puppet.puppet_version}} BUNDLE_WITHOUT: 'acceptance:system_tests' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.puppet.ruby_version}} @@ -47,7 +47,7 @@ jobs: PUPPET_VERSION: ${{matrix.puppet.puppet_version}} BUNDLE_WITHOUT: 'acceptance:system_tests' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.puppet.ruby_version}} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 903e71b..3d8a8fc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -14,6 +14,8 @@ 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