diff --git a/.fixtures.yml b/.fixtures.yml index 1e57f657..dbfba303 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,6 +1,5 @@ +--- fixtures: repositories: stdlib: https://github.com/puppetlabs/puppetlabs-stdlib.git - selinux_core: - repo: https://github.com/puppetlabs/puppetlabs-selinux_core.git - puppet_version: ">= 6.0.0" + selinux_core: https://github.com/puppetlabs/puppetlabs-selinux_core.git diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 048d2b55..8b466cfb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -124,7 +124,7 @@ If you have Ruby 2.x or want a specific version of Puppet, you must set an environment variable such as: ```sh -export PUPPET_VERSION="~> 5.5.6" +export PUPPET_GEM_VERSION="~> 6.1.0" ``` You can install all needed gems for spec tests into the modules directory by @@ -232,17 +232,16 @@ simple tests against it after applying the module. You can run this with: ```sh -BEAKER_setfile=debian10-x64 bundle exec rake beaker +BEAKER_setfile=debian11-64 bundle exec rake beaker ``` You can replace the string `debian10` with any common operating system. The following strings are known to work: -* ubuntu1604 * ubuntu1804 * ubuntu2004 -* debian9 * debian10 +* debian11 * centos7 * centos8 diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index cacadf22..00000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,3 +0,0 @@ -# Vox Pupuli Security Policy - -Our vulnerabilities reporting process is at https://voxpupuli.org/security/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2582dbab..49981e36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,57 +6,11 @@ name: CI on: pull_request -jobs: - setup_matrix: - name: 'Setup Test Matrix' - runs-on: ubuntu-latest - timeout-minutes: 40 - outputs: - puppet_unit_test_matrix: ${{ steps.get-outputs.outputs.puppet_unit_test_matrix }} - github_action_test_matrix: ${{ steps.get-outputs.outputs.github_action_test_matrix }} - env: - BUNDLE_WITHOUT: development:system_tests:release - steps: - - uses: actions/checkout@v2 - - name: Setup ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '3.0' - bundler-cache: true - - name: Run static validations - run: bundle exec rake validate lint check - - name: Run rake rubocop - run: bundle exec rake rubocop - - name: Setup Test Matrix - id: get-outputs - run: bundle exec metadata2gha --use-fqdn --pidfile-workaround false - - unit: - needs: setup_matrix - runs-on: ubuntu-latest - timeout-minutes: 40 - strategy: - fail-fast: false - matrix: - include: ${{fromJson(needs.setup_matrix.outputs.puppet_unit_test_matrix)}} - env: - BUNDLE_WITHOUT: development:system_tests:release - PUPPET_VERSION: "~> ${{ matrix.puppet }}.0" - name: Puppet ${{ matrix.puppet }} (Ruby ${{ matrix.ruby }}) - steps: - - uses: actions/checkout@v2 - - name: Setup ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - bundler-cache: true - - name: Run tests - run: bundle exec rake parallel_spec +concurrency: + group: ${{ github.ref_name }} + cancel-in-progress: true - tests: - needs: - - unit - runs-on: ubuntu-latest - name: Test suite - steps: - - run: echo Test suite completed +jobs: + puppet: + name: Puppet + uses: voxpupuli/gha-puppet/.github/workflows/basic.yml@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 664ba694..15f17213 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,26 +9,14 @@ on: tags: - '*' -env: - BUNDLE_WITHOUT: development:test:system_tests - jobs: - deploy: - name: 'deploy to forge' - runs-on: ubuntu-latest - if: github.repository_owner == 'voxpupuli' - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: '2.7' - bundler-cache: true - - name: Build and Deploy - env: - # Configure secrets here: - # https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets - BLACKSMITH_FORGE_USERNAME: '${{ secrets.PUPPET_FORGE_USERNAME }}' - BLACKSMITH_FORGE_API_KEY: '${{ secrets.PUPPET_FORGE_API_KEY }}' - run: bundle exec rake module:push + release: + name: Release + uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v1 + with: + allowed_owner: 'voxpupuli' + secrets: + # Configure secrets here: + # https://docs.github.com/en/actions/security-guides/encrypted-secrets + username: ${{ secrets.PUPPET_FORGE_USERNAME }} + api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} diff --git a/.gitignore b/.gitignore index 9b95224c..84fd904c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,23 @@ # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -pkg/ -Gemfile.lock -Gemfile.local -vendor/ -.vendor/ -spec/fixtures/manifests/ -spec/fixtures/modules/ -.vagrant/ -.bundle/ -.ruby-version -coverage/ -log/ -.idea/ -.dependencies/ -.librarian/ -Puppetfile.lock +/pkg/ +/Gemfile.lock +/Gemfile.local +/vendor/ +/.vendor/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/.vagrant/ +/.bundle/ +/.ruby-version +/coverage/ +/log/ +/.idea/ +/.dependencies/ +/.librarian/ +/Puppetfile.lock *.iml .*.sw? -.yardoc/ -Guardfile +/.yardoc/ +/Guardfile diff --git a/.msync.yml b/.msync.yml index 43966c2f..b929160c 100644 --- a/.msync.yml +++ b/.msync.yml @@ -2,4 +2,4 @@ # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -modulesync_config_version: '4.2.0' +modulesync_config_version: '6.0.0' diff --git a/.pmtignore b/.pmtignore index 5579c98a..58a04088 100644 --- a/.pmtignore +++ b/.pmtignore @@ -1,38 +1,37 @@ # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -docs/ -pkg/ -Gemfile -Gemfile.lock -Gemfile.local -vendor/ -.vendor/ -spec/ -Rakefile -.vagrant/ -.bundle/ -.ruby-version -coverage/ -log/ -.idea/ -.dependencies/ -.github/ -.librarian/ -Puppetfile.lock +/docs/ +/pkg/ +/Gemfile +/Gemfile.lock +/Gemfile.local +/vendor/ +/.vendor/ +/spec/ +/Rakefile +/.vagrant/ +/.bundle/ +/.ruby-version +/coverage/ +/log/ +/.idea/ +/.dependencies/ +/.github/ +/.librarian/ +/Puppetfile.lock *.iml -.editorconfig -.fixtures.yml -.gitignore -.msync.yml -.overcommit.yml -.pmtignore -.rspec -.rspec_parallel -.rubocop.yml -.sync.yml +/.editorconfig +/.fixtures.yml +/.gitignore +/.msync.yml +/.overcommit.yml +/.pmtignore +/.rspec +/.rspec_parallel +/.rubocop.yml +/.sync.yml .*.sw? -.yardoc/ -.yardopts -Dockerfile -.puppet-lint.rc +/.yardoc/ +/.yardopts +/Dockerfile diff --git a/.puppet-lint.rc b/.puppet-lint.rc index a8e50faa..c823c263 100644 --- a/.puppet-lint.rc +++ b/.puppet-lint.rc @@ -1 +1,2 @@ +--fail-on-warnings --no-anchor_resource-check diff --git a/.rubocop.yml b/.rubocop.yml index 53ac1898..ea22bff8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,6 @@ --- +inherit_from: .rubocop_todo.yml + # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..77a987dd --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,38 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2023-06-29 07:44:45 UTC using RuboCop version 1.22.3. +# 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: 1 +# Cop supports --auto-correct. +Lint/AmbiguousOperatorPrecedence: + Exclude: + - 'lib/puppet/provider/selinux_login/semanage.rb' + +# Offense count: 2 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'lib/puppet/provider/selinux_login/semanage.rb' + - 'lib/puppet/provider/selinux_port/semanage.rb' + +# Offense count: 1 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 6 + +# Offense count: 1 +# Cop supports --auto-correct. +Style/ExpandPathArguments: + Exclude: + - 'lib/puppet/provider/selinux_login/semanage.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Exclude: + - 'lib/puppet/provider/selinux_login/semanage.rb' diff --git a/.sync.yml b/.sync.yml index 96615056..b65e3149 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,10 +1,9 @@ --- -.pmtignore: - paths: - - .puppet-lint.rc spec/spec_helper.rb: mock_with: ':mocha' -Gemfile: - optional: - ':test': - - gem: puppet-lint-param-docs +.puppet-lint.rc: + disabled_lint_checks: + - anchor_resource + enabled_lint_checks: + - parameter_documentation + - parameter_types diff --git a/Dockerfile b/Dockerfile index e3cf307f..8dd82d63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ WORKDIR /opt/puppet # https://github.com/puppetlabs/puppet/blob/06ad255754a38f22fb3a22c7c4f1e2ce453d01cb/lib/puppet/provider/service/runit.rb#L39 RUN mkdir -p /etc/sv -ARG PUPPET_VERSION="~> 6.0" +ARG PUPPET_GEM_VERSION="~> 6.0" ARG PARALLEL_TEST_PROCESSORS=4 # Cache gems diff --git a/Gemfile b/Gemfile index e43173e0..98a04cfb 100644 --- a/Gemfile +++ b/Gemfile @@ -1,14 +1,13 @@ # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -source ENV['GEM_SOURCE'] || "https://rubygems.org" +source ENV['GEM_SOURCE'] || 'https://rubygems.org' group :test do - gem 'voxpupuli-test', '~> 2.5', :require => false + gem 'voxpupuli-test', '~> 6.0', :require => false gem 'coveralls', :require => false gem 'simplecov-console', :require => false - gem 'puppet_metadata', '~> 1.0', :require => false - gem 'puppet-lint-param-docs', :require => false + gem 'puppet_metadata', '~> 3.0', :require => false end group :development do @@ -17,19 +16,19 @@ group :development do end group :system_tests do - gem 'voxpupuli-acceptance', '~> 1.0', :require => false + gem 'voxpupuli-acceptance', '~> 2.0', :require => false end group :release do - gem 'github_changelog_generator', '>= 1.16.1', :require => false if RUBY_VERSION >= '2.5' - gem 'voxpupuli-release', '>= 1.0.2', :require => false - gem 'puppet-strings', '>= 2.2', :require => false + gem 'github_changelog_generator', '>= 1.16.1', :require => false + gem 'voxpupuli-release', '~> 3.0', :require => false + gem 'faraday-retry', '~> 2.1', :require => false end gem 'rake', :require => false gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] -puppetversion = ENV['PUPPET_VERSION'] || '>= 6.0' +puppetversion = ENV['PUPPET_GEM_VERSION'] || '~> 7.24' gem 'puppet', puppetversion, :require => false, :groups => [:test] # vim: syntax=ruby diff --git a/REFERENCE.md b/REFERENCE.md index 0d4e3d42..ec6ab380 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -19,18 +19,20 @@ ### Defined types -* [`selinux::boolean`](#selinuxboolean): Manage the state of an SELinux boolean. -* [`selinux::exec_restorecon`](#selinuxexec_restorecon): A convenience wrapper around a restorecon exec -* [`selinux::fcontext`](#selinuxfcontext): For fcontext equivalences, see selinux::fcontext::equivalence -* [`selinux::fcontext::equivalence`](#selinuxfcontextequivalence): Manage SELinux fcontext equivalences -* [`selinux::module`](#selinuxmodule): Manage a SELinux module on a running system -* [`selinux::permissive`](#selinuxpermissive): Set SELinux type to permissive -* [`selinux::port`](#selinuxport): Manage a SELinux local network port context setting +* [`selinux::boolean`](#selinux--boolean): Manage the state of an SELinux boolean. +* [`selinux::exec_restorecon`](#selinux--exec_restorecon): A convenience wrapper around a restorecon exec +* [`selinux::fcontext`](#selinux--fcontext): For fcontext equivalences, see selinux::fcontext::equivalence +* [`selinux::fcontext::equivalence`](#selinux--fcontext--equivalence): Manage SELinux fcontext equivalences +* [`selinux::login`](#selinux--login): Manage a SELinux login +* [`selinux::module`](#selinux--module): Manage a SELinux module on a running system +* [`selinux::permissive`](#selinux--permissive): Set SELinux type to permissive +* [`selinux::port`](#selinux--port): Manage a SELinux local network port context setting ### Resource types * [`selinux_fcontext`](#selinux_fcontext): Manage SELinux fcontext definitions. You should use selinux::fcontext instead of this directly. * [`selinux_fcontext_equivalence`](#selinux_fcontext_equivalence): Manage SELinux fcontext equivalence definitions. You should use selinux::fcontext instead of this directly. +* [`selinux_login`](#selinux_login): Manage SELinux login definitions. You should use selinux::login instead of this directly. * [`selinux_permissive`](#selinux_permissive): Manage SELinux permissive types. * [`selinux_port`](#selinux_port): Manage SELinux port definitions. You should use selinux::port instead of this directly. @@ -55,33 +57,37 @@ class { 'selinux': The following parameters are available in the `selinux` class: -* [`package_name`](#package_name) -* [`manage_auditd_package`](#manage_auditd_package) -* [`refpolicy_package_name`](#refpolicy_package_name) -* [`mode`](#mode) -* [`type`](#type) -* [`refpolicy_makefile`](#refpolicy_makefile) -* [`manage_package`](#manage_package) -* [`auditd_package_name`](#auditd_package_name) -* [`manage_setroubleshoot_packages`](#manage_setroubleshoot_packages) -* [`setroubleshoot_package_names`](#setroubleshoot_package_names) -* [`module_build_root`](#module_build_root) -* [`default_builder`](#default_builder) -* [`boolean`](#boolean) -* [`fcontext`](#fcontext) -* [`module`](#module) -* [`permissive`](#permissive) -* [`port`](#port) -* [`exec_restorecon`](#exec_restorecon) - -##### `package_name` +* [`package_name`](#-selinux--package_name) +* [`manage_auditd_package`](#-selinux--manage_auditd_package) +* [`refpolicy_package_name`](#-selinux--refpolicy_package_name) +* [`mode`](#-selinux--mode) +* [`type`](#-selinux--type) +* [`refpolicy_makefile`](#-selinux--refpolicy_makefile) +* [`manage_package`](#-selinux--manage_package) +* [`auditd_package_name`](#-selinux--auditd_package_name) +* [`manage_setroubleshoot_packages`](#-selinux--manage_setroubleshoot_packages) +* [`manage_selinux_sandbox_packages`](#-selinux--manage_selinux_sandbox_packages) +* [`setroubleshoot_package_names`](#-selinux--setroubleshoot_package_names) +* [`selinux_sandbox_package_names`](#-selinux--selinux_sandbox_package_names) +* [`module_build_root`](#-selinux--module_build_root) +* [`default_builder`](#-selinux--default_builder) +* [`boolean`](#-selinux--boolean) +* [`fcontext`](#-selinux--fcontext) +* [`fcontext_equivalence`](#-selinux--fcontext_equivalence) +* [`module`](#-selinux--module) +* [`permissive`](#-selinux--permissive) +* [`port`](#-selinux--port) +* [`exec_restorecon`](#-selinux--exec_restorecon) +* [`login`](#-selinux--login) + +##### `package_name` Data type: `Variant[String[1], Array[String[1]]]` sets the name(s) for the selinux tools package Default value: OS dependent (see data/). -##### `manage_auditd_package` +##### `manage_auditd_package` Data type: `Boolean` @@ -89,7 +95,7 @@ install auditd to log SELinux violations, for OSes that do not have auditd installed by default. Default value: OS dependent (see data/) -##### `refpolicy_package_name` +##### `refpolicy_package_name` Data type: `String` @@ -97,23 +103,23 @@ sets the name for the refpolicy development package, required for the refpolicy module builder Default value: OS dependent (see data/) -##### `mode` +##### `mode` Data type: `Optional[Enum['enforcing', 'permissive', 'disabled']]` sets the operating state for SELinux. -Default value: ``undef`` +Default value: `undef` -##### `type` +##### `type` Data type: `Optional[Enum['targeted', 'minimum', 'mls']]` sets the selinux type -Default value: ``undef`` +Default value: `undef` -##### `refpolicy_makefile` +##### `refpolicy_makefile` Data type: `Stdlib::Absolutepath` @@ -121,15 +127,15 @@ the path to the system's SELinux makefile for the refpolicy framework Default value: `'/usr/share/selinux/devel/Makefile'` -##### `manage_package` +##### `manage_package` Data type: `Boolean` manage the package for selinux tools and refpolicy -Default value: ``true`` +Default value: `true` -##### `auditd_package_name` +##### `auditd_package_name` Data type: `String[1]` @@ -137,13 +143,19 @@ used when `manage_auditd_package` is true Default value: `'auditd'` -##### `manage_setroubleshoot_packages` +##### `manage_setroubleshoot_packages` Data type: `Boolean` manage the setroubleshoot packages -##### `setroubleshoot_package_names` +##### `manage_selinux_sandbox_packages` + +Data type: `Boolean` + +manage the selinux sandbox packages + +##### `setroubleshoot_package_names` Data type: `Array[String]` @@ -151,7 +163,15 @@ the names of the setroubleshoot packages Default value: `[]` -##### `module_build_root` +##### `selinux_sandbox_package_names` + +Data type: `Array[String]` + +the names of the selinux sandbox packages + +Default value: `[]` + +##### `module_build_root` Data type: `Stdlib::Absolutepath` @@ -159,7 +179,7 @@ directory where modules are built. Defaults to `$vardir/puppet-selinux` Default value: `"${facts['puppet_vardir']}/puppet-selinux"` -##### `default_builder` +##### `default_builder` Data type: `Enum['refpolicy', 'simple']` @@ -167,57 +187,73 @@ which builder to use by default with selinux::module Default value: `'simple'` -##### `boolean` +##### `boolean` Data type: `Optional[Hash]` Hash of selinux::boolean resource parameters -Default value: ``undef`` +Default value: `undef` -##### `fcontext` +##### `fcontext` Data type: `Optional[Hash]` Hash of selinux::fcontext resource parameters -Default value: ``undef`` +Default value: `undef` -##### `module` +##### `fcontext_equivalence` + +Data type: `Optional[Hash]` + +Hash of selinux::fcontext::equivalence resource parameters + +Default value: `undef` + +##### `module` Data type: `Optional[Hash]` Hash of selinux::module resource parameters -Default value: ``undef`` +Default value: `undef` -##### `permissive` +##### `permissive` Data type: `Optional[Hash]` Hash of selinux::module resource parameters -Default value: ``undef`` +Default value: `undef` -##### `port` +##### `port` Data type: `Optional[Hash]` Hash of selinux::port resource parameters -Default value: ``undef`` +Default value: `undef` -##### `exec_restorecon` +##### `exec_restorecon` Data type: `Optional[Hash]` Hash of selinux::exec_restorecon resource parameters -Default value: ``undef`` +Default value: `undef` + +##### `login` + +Data type: `Hash[String[1],Hash[String[1],String[1]]]` + +Hash of selinux::login resource parameters + +Default value: `{}` ## Defined types -### `selinux::boolean` +### `selinux::boolean` Manage the state of an SELinux boolean. @@ -243,10 +279,10 @@ selinux::boolean{ 'named_write_master_zones': The following parameters are available in the `selinux::boolean` defined type: -* [`ensure`](#ensure) -* [`persistent`](#persistent) +* [`ensure`](#-selinux--boolean--ensure) +* [`persistent`](#-selinux--boolean--persistent) -##### `ensure` +##### `ensure` Data type: `Variant[Boolean, Enum['on', 'off', 'present', 'absent']]` @@ -254,15 +290,15 @@ Set to on or off Default value: `'on'` -##### `persistent` +##### `persistent` Data type: `Boolean` Set to false if you don't want it to survive a reboot. -Default value: ``true`` +Default value: `true` -### `selinux::exec_restorecon` +### `selinux::exec_restorecon` Will execute after all other SELinux changes have been applied, but before Anchor['selinux::end'] @@ -271,14 +307,14 @@ Anchor['selinux::end'] The following parameters are available in the `selinux::exec_restorecon` defined type: -* [`path`](#path) -* [`recurse`](#recurse) -* [`force`](#force) -* [`refreshonly`](#refreshonly) -* [`unless`](#unless) -* [`onlyif`](#onlyif) +* [`path`](#-selinux--exec_restorecon--path) +* [`recurse`](#-selinux--exec_restorecon--recurse) +* [`force`](#-selinux--exec_restorecon--force) +* [`refreshonly`](#-selinux--exec_restorecon--refreshonly) +* [`unless`](#-selinux--exec_restorecon--unless) +* [`onlyif`](#-selinux--exec_restorecon--onlyif) -##### `path` +##### `path` Data type: `Stdlib::Absolutepath` @@ -286,47 +322,47 @@ The path to run restorecon on. Defaults to resource title. Default value: `$title` -##### `recurse` +##### `recurse` Data type: `Boolean` Whether restorecon should recurse. Defaults to true -Default value: ``true`` +Default value: `true` -##### `force` +##### `force` Data type: `Boolean` Whether restorecon should use force. Defaults to false. -Default value: ``false`` +Default value: `false` -##### `refreshonly` +##### `refreshonly` Data type: `Boolean` see the Exec resource -Default value: ``true`` +Default value: `true` -##### `unless` +##### `unless` Data type: `Optional[String]` see the Exec resource -Default value: ``undef`` +Default value: `undef` -##### `onlyif` +##### `onlyif` Data type: `Optional[String]` see the Exec resource -Default value: ``undef`` +Default value: `undef` -### `selinux::fcontext` +### `selinux::fcontext` For fcontext equivalences, see selinux::fcontext::equivalence @@ -357,13 +393,13 @@ selinux::fcontext{'/u/users/[^/]*': The following parameters are available in the `selinux::fcontext` defined type: -* [`ensure`](#ensure) -* [`seltype`](#seltype) -* [`seluser`](#seluser) -* [`pathspec`](#pathspec) -* [`filetype`](#filetype) +* [`ensure`](#-selinux--fcontext--ensure) +* [`seltype`](#-selinux--fcontext--seltype) +* [`seluser`](#-selinux--fcontext--seluser) +* [`pathspec`](#-selinux--fcontext--pathspec) +* [`filetype`](#-selinux--fcontext--filetype) -##### `ensure` +##### `ensure` Data type: `Enum['absent', 'present']` @@ -371,23 +407,23 @@ The desired state of the resource. Default: 'present' Default value: `'present'` -##### `seltype` +##### `seltype` Data type: `Optional[String]` String A particular SELinux type, like "mysqld_log_t" -Default value: ``undef`` +Default value: `undef` -##### `seluser` +##### `seluser` Data type: `Optional[String]` String A particular SELinux user, like "sysadm_u" -Default value: ``undef`` +Default value: `undef` -##### `pathspec` +##### `pathspec` Data type: `String` @@ -396,7 +432,7 @@ like "/var/log/mysql(/.*)?". Defaults to title Default value: `$title` -##### `filetype` +##### `filetype` Data type: `String[1]` @@ -413,7 +449,7 @@ File type the context applies to (i.e. regular file, directory, block device, al Default value: `'a'` -### `selinux::fcontext::equivalence` +### `selinux::fcontext::equivalence` Manage SELinux fcontext equivalences @@ -432,11 +468,11 @@ selinux::fcontext::equivalence { '/opt/wordpress': The following parameters are available in the `selinux::fcontext::equivalence` defined type: -* [`path`](#path) -* [`target`](#target) -* [`ensure`](#ensure) +* [`path`](#-selinux--fcontext--equivalence--path) +* [`target`](#-selinux--fcontext--equivalence--target) +* [`ensure`](#-selinux--fcontext--equivalence--ensure) -##### `path` +##### `path` Data type: `String` @@ -444,13 +480,13 @@ the path to define and equivalence for. Default: Resource title Default value: `$title` -##### `target` +##### `target` Data type: `String` the path that this resource will be equivalent to. -##### `ensure` +##### `ensure` Data type: `Enum['present', 'absent']` @@ -458,7 +494,52 @@ the desired state of the equivalence. Default: present Default value: `'present'` -### `selinux::module` +### `selinux::login` + +This method will manage a selinux login, and will +persist it across reboots. + +#### Examples + +##### Add a map for the localuser to staff_u + +```puppet +selinux::login { 'localuser_staff_u': + ensure => 'present', + selinux_login_name => 'localuser', + selinux_user => 'staff_u', +} +``` + +#### Parameters + +The following parameters are available in the `selinux::login` defined type: + +* [`ensure`](#-selinux--login--ensure) +* [`selinux_login_name`](#-selinux--login--selinux_login_name) +* [`selinux_user`](#-selinux--login--selinux_user) + +##### `ensure` + +Data type: `Enum['present', 'absent']` + +Set to present to add or absent to remove a selinux login. + +Default value: `'present'` + +##### `selinux_login_name` + +Data type: `String[1]` + +A Linux user or group + +##### `selinux_user` + +Data type: `String[1]` + +The selinux user to map to + +### `selinux::module` This class will either install or uninstall a SELinux module from a running system. This module allows an admin to keep .te files in text form in a repository, while @@ -516,17 +597,17 @@ selinux::module{ 'zabbix_fix': The following parameters are available in the `selinux::module` defined type: -* [`ensure`](#ensure) -* [`source_pp`](#source_pp) -* [`source_te`](#source_te) -* [`source_fc`](#source_fc) -* [`source_if`](#source_if) -* [`content_te`](#content_te) -* [`content_fc`](#content_fc) -* [`content_if`](#content_if) -* [`builder`](#builder) +* [`ensure`](#-selinux--module--ensure) +* [`source_pp`](#-selinux--module--source_pp) +* [`source_te`](#-selinux--module--source_te) +* [`source_fc`](#-selinux--module--source_fc) +* [`source_if`](#-selinux--module--source_if) +* [`content_te`](#-selinux--module--content_te) +* [`content_fc`](#-selinux--module--content_fc) +* [`content_if`](#-selinux--module--content_if) +* [`builder`](#-selinux--module--builder) -##### `ensure` +##### `ensure` Data type: `Enum['absent', 'present']` @@ -534,73 +615,73 @@ present or absent Default value: `'present'` -##### `source_pp` +##### `source_pp` Data type: `Optional[String]` the source file (either a puppet URI or local file) of a pre-compiled SELinux policy package. Mutually excludsive with using source files. -Default value: ``undef`` +Default value: `undef` -##### `source_te` +##### `source_te` Data type: `Optional[String]` the source file (either a puppet URI or local file) of the SELinux .te file -Default value: ``undef`` +Default value: `undef` -##### `source_fc` +##### `source_fc` Data type: `Optional[String]` the source file (either a puppet URI or local file) of the SELinux .fc file -Default value: ``undef`` +Default value: `undef` -##### `source_if` +##### `source_if` Data type: `Optional[String]` the source file (either a puppet URI or local file) of the SELinux .if file -Default value: ``undef`` +Default value: `undef` -##### `content_te` +##### `content_te` Data type: `Optional[String]` content of the SELinux .te file -Default value: ``undef`` +Default value: `undef` -##### `content_fc` +##### `content_fc` Data type: `Optional[String]` content of the SELinux .fc file -Default value: ``undef`` +Default value: `undef` -##### `content_if` +##### `content_if` Data type: `Optional[String]` content of the SELinux .if file -Default value: ``undef`` +Default value: `undef` -##### `builder` +##### `builder` Data type: `Optional[Enum['simple', 'refpolicy']]` either 'simple' or 'refpolicy'. The simple builder attempts to use checkmodule to build the module, whereas 'refpolicy' uses the refpolicy framework, but requires 'make' -Default value: ``undef`` +Default value: `undef` -### `selinux::permissive` +### `selinux::permissive` Set SELinux type to permissive @@ -618,10 +699,10 @@ selinux::permissive { 'oddjob_mkhomedir_t': The following parameters are available in the `selinux::permissive` defined type: -* [`ensure`](#ensure) -* [`seltype`](#seltype) +* [`ensure`](#-selinux--permissive--ensure) +* [`seltype`](#-selinux--permissive--seltype) -##### `ensure` +##### `ensure` Data type: `Enum['present', 'absent']` @@ -629,7 +710,7 @@ Set to present to add or absent to remove a permissive mode of a type Default value: `'present'` -##### `seltype` +##### `seltype` Data type: `String` @@ -637,7 +718,7 @@ A particular selinux type to make permissive, like "oddjob_mkhomedir_t" Default value: `$title` -### `selinux::port` +### `selinux::port` This method will manage a local network port context setting, and will persist it across reboots. @@ -659,13 +740,13 @@ selinux::port { 'allow-syslog-relp': The following parameters are available in the `selinux::port` defined type: -* [`ensure`](#ensure) -* [`seltype`](#seltype) -* [`protocol`](#protocol) -* [`port`](#port) -* [`port_range`](#port_range) +* [`ensure`](#-selinux--port--ensure) +* [`seltype`](#-selinux--port--seltype) +* [`protocol`](#-selinux--port--protocol) +* [`port`](#-selinux--port--port) +* [`port_range`](#-selinux--port--port_range) -##### `ensure` +##### `ensure` Data type: `Enum['present', 'absent']` @@ -673,33 +754,33 @@ Set to present to add or absent to remove a port context. Default value: `'present'` -##### `seltype` +##### `seltype` Data type: `String` An SELinux port type -##### `protocol` +##### `protocol` Data type: `Enum['tcp', 'udp']` Either 'tcp', 'udp', 'ipv4' or 'ipv6' -##### `port` +##### `port` Data type: `Optional[Integer[1,65535]]` A network port number, like 8514, -Default value: ``undef`` +Default value: `undef` -##### `port_range` +##### `port_range` Data type: `Optional[Tuple[Integer[1,65535], 2, 2]]` A port-range tuple, eg. [9090, 9095]. -Default value: ``undef`` +Default value: `undef` ## Resource types @@ -755,20 +836,20 @@ The SELinux user name The following parameters are available in the `selinux_fcontext` type. -* [`pathspec`](#pathspec) -* [`provider`](#provider) -* [`title`](#title) +* [`pathspec`](#-selinux_fcontext--pathspec) +* [`provider`](#-selinux_fcontext--provider) +* [`title`](#-selinux_fcontext--title) -##### `pathspec` +##### `pathspec` Path regular expression -##### `provider` +##### `provider` The specific backend to use for this `selinux_fcontext` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. -##### `title` +##### `title` The namevar. Should be of the format pathspec_filetype @@ -796,18 +877,58 @@ The target of the equivalence. ie. the path that this resource will be equivalen The following parameters are available in the `selinux_fcontext_equivalence` type. -* [`path`](#path) -* [`provider`](#provider) +* [`path`](#-selinux_fcontext_equivalence--path) +* [`provider`](#-selinux_fcontext_equivalence--provider) -##### `path` +##### `path` The path to set equivalence for -##### `provider` +##### `provider` The specific backend to use for this `selinux_fcontext_equivalence` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. +### `selinux_login` + +Manage SELinux login definitions. You should use selinux::login instead of this directly. + +#### Properties + +The following properties are available in the `selinux_login` type. + +##### `ensure` + +Valid values: `present`, `absent` + +The basic property that the resource should be in. + +Default value: `present` + +##### `selinux_login_name` + +The name of the linux user or group to map. + +##### `selinux_user` + +The selinux user to map to. + +#### Parameters + +The following parameters are available in the `selinux_login` type. + +* [`provider`](#-selinux_login--provider) +* [`title`](#-selinux_login--title) + +##### `provider` + +The specific backend to use for this `selinux_login` resource. You will seldom need to specify this --- Puppet will +usually discover the appropriate provider for your platform. + +##### `title` + +Should be of the form "linuxuser_selinuxuser" or the type may misbehave + ### `selinux_permissive` Manage SELinux permissive types. @@ -828,22 +949,22 @@ Default value: `present` The following parameters are available in the `selinux_permissive` type. -* [`local`](#local) -* [`provider`](#provider) -* [`seltype`](#seltype) +* [`local`](#-selinux_permissive--local) +* [`provider`](#-selinux_permissive--provider) +* [`seltype`](#-selinux_permissive--seltype) -##### `local` +##### `local` -Valid values: ``true``, ``false`` +Valid values: `true`, `false` A read-only attribue indicating whether the type is locally customized -##### `provider` +##### `provider` The specific backend to use for this `selinux_permissive` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. -##### `seltype` +##### `seltype` namevar @@ -893,15 +1014,15 @@ Source of the port configuration - either policy or local The following parameters are available in the `selinux_port` type. -* [`provider`](#provider) -* [`title`](#title) +* [`provider`](#-selinux_port--provider) +* [`title`](#-selinux_port--title) -##### `provider` +##### `provider` The specific backend to use for this `selinux_port` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. -##### `title` +##### `title` Should be of the form "protocol_lowport-highport" or the type may misbehave diff --git a/Rakefile b/Rakefile index 80b799d6..90273ba8 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,7 @@ # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -# Attempt to load voxupuli-test (which pulls in puppetlabs_spec_helper), +# Attempt to load voxpupuli-test (which pulls in puppetlabs_spec_helper), # otherwise attempt to load it directly. begin require 'voxpupuli/test/rake' @@ -24,6 +24,10 @@ end begin require 'voxpupuli/release/rake_tasks' rescue LoadError + # voxpupuli-release not present +else + GCGConfig.user = 'voxpupuli' + GCGConfig.project = 'puppet-selinux' end desc "Run main 'test' task and report merged results to coveralls" @@ -37,36 +41,4 @@ task test_with_coveralls: [:test] do end end -desc 'Generate REFERENCE.md' -task :reference, [:debug, :backtrace] do |t, args| - patterns = '' - Rake::Task['strings:generate:reference'].invoke(patterns, args[:debug], args[:backtrace]) -end - -begin - require 'github_changelog_generator/task' - require 'puppet_blacksmith' - GitHubChangelogGenerator::RakeTask.new :changelog do |config| - metadata = Blacksmith::Modulefile.new - config.future_release = "v#{metadata.version}" if metadata.version =~ /^\d+\.\d+.\d+$/ - config.header = "# Changelog\n\nAll notable changes to this project will be documented in this file.\nEach new release typically also includes the latest modulesync defaults.\nThese should not affect the functionality of the module." - config.exclude_labels = %w{duplicate question invalid wontfix wont-fix modulesync skip-changelog} - config.user = 'voxpupuli' - config.project = metadata.metadata['name'] - end - - # Workaround for https://github.com/github-changelog-generator/github-changelog-generator/issues/715 - require 'rbconfig' - if RbConfig::CONFIG['host_os'] =~ /linux/ - task :changelog do - puts 'Fixing line endings...' - changelog_file = File.join(__dir__, 'CHANGELOG.md') - changelog_txt = File.read(changelog_file) - new_contents = changelog_txt.gsub(%r{\r\n}, "\n") - File.open(changelog_file, "w") {|file| file.puts new_contents } - end - end - -rescue LoadError -end # vim: syntax=ruby diff --git a/lib/facter/selinux_python_command.rb b/lib/facter/selinux_python_command.rb index f903dee2..8316f2b5 100644 --- a/lib/facter/selinux_python_command.rb +++ b/lib/facter/selinux_python_command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # DEPRECATED: Determine the path to python on the system Facter.add(:selinux_python_command) do confine osfamily: 'RedHat' diff --git a/lib/puppet/provider/selinux_fcontext/semanage.rb b/lib/puppet/provider/selinux_fcontext/semanage.rb index 36f7cb82..d8c66b97 100644 --- a/lib/puppet/provider/selinux_fcontext/semanage.rb +++ b/lib/puppet/provider/selinux_fcontext/semanage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.type(:selinux_fcontext).provide(:semanage) do desc 'Support managing SELinux custom fcontext definitions via semanage' @@ -28,6 +30,7 @@ def self.file_type_map(val) def self.type_param(file_type) return file_type unless @old_semanage + @file_types.invert[file_type] end @@ -36,6 +39,7 @@ def self.parse_fcontext_lines(lines) lines.each do |line| next if line.strip.empty? next if line =~ %r{^#} + split = line.split(%r{\s+}) if split.length == 2 path_spec, context_spec = split @@ -63,6 +67,7 @@ def self.parse_fcontext_lines(lines) def self.parse_fcontext_file(path) return [] unless File.exist?(path) + parse_fcontext_lines(File.readlines(path)) end diff --git a/lib/puppet/provider/selinux_fcontext_equivalence/semanage.rb b/lib/puppet/provider/selinux_fcontext_equivalence/semanage.rb index be439359..fa68c1cc 100644 --- a/lib/puppet/provider/selinux_fcontext_equivalence/semanage.rb +++ b/lib/puppet/provider/selinux_fcontext_equivalence/semanage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.type(:selinux_fcontext_equivalence).provide(:semanage) do desc 'Support managing SELinux custom fcontext definitions via semanage' @@ -13,6 +15,7 @@ def self.parse_fcontext_subs_lines(lines) lines.each do |line| next if line.strip.empty? next if line =~ %r{^#} + source, target = line.split(%r{\s+}) ret.push(new(ensure: :present, name: source, diff --git a/lib/puppet/provider/selinux_login/semanage.rb b/lib/puppet/provider/selinux_login/semanage.rb index 7eafb2b1..65590803 100644 --- a/lib/puppet/provider/selinux_login/semanage.rb +++ b/lib/puppet/provider/selinux_login/semanage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.type(:selinux_login).provide(:semanage) do desc 'Support managing SELinux login definitions via semanage' @@ -24,6 +26,7 @@ def self.python_command candidate = Puppet::Util.which(pypath) next unless candidate + valid_paths << candidate if Puppet::Util::Execution.execute("#{candidate} -c 'import semanage'", failonfail: false).exitstatus.zero? @@ -90,11 +93,13 @@ def self.prefetch(resources) unless resource[:selinux_user].to_s == provider.selinux_user && resource[:selinux_login_name].to_s == provider.selinux_login_name || resource.purging? raise Puppet::ResourceError, "Selinux_port['#{resource[:name]}']: title does not match its port and protocol, and a conflicting resource exists" end + resource.provider = provider resource[:ensure] = :present if provider.source == :policy else - resources.values.each do |res| + resources.each_value do |res| next unless res[:selinux_user] == provider.selinux_user && res[:selinux_login_name] == provider.selinux_login_name + warning("Selinux_login['#{resource[:name]}']: title does not match format selinux_login_name_selinux_user") resource.provider = provider resource[:ensure] = :present if provider.source == :policy diff --git a/lib/puppet/provider/selinux_permissive/semanage.rb b/lib/puppet/provider/selinux_permissive/semanage.rb index 33e7a8f0..836851fd 100644 --- a/lib/puppet/provider/selinux_permissive/semanage.rb +++ b/lib/puppet/provider/selinux_permissive/semanage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.type(:selinux_permissive).provide(:semanage) do desc 'Support managing SELinux permissive types definitions via semanage' @@ -25,6 +27,7 @@ def self.instances next end next if line.strip.empty? + name = line.strip # do not use built-in provider if we find a customized type next if res[name] && !local @@ -41,6 +44,7 @@ def self.prefetch(resources) resource = resources[provider.seltype] # consider built-in resources absent for purposes of purging next unless resource + resource.provider = provider if resource.purging? && !provider.local debug("Can't purge built-in resource #{resource[:seltype]}") diff --git a/lib/puppet/provider/selinux_port/semanage.rb b/lib/puppet/provider/selinux_port/semanage.rb index cb0d1262..f5ae2ae5 100644 --- a/lib/puppet/provider/selinux_port/semanage.rb +++ b/lib/puppet/provider/selinux_port/semanage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.type(:selinux_port).provide(:semanage) do desc 'Support managing SELinux custom port definitions via semanage' @@ -24,6 +26,7 @@ def self.python_command candidate = Puppet::Util.which(pypath) next unless candidate + valid_paths << candidate if Puppet::Util::Execution.execute("#{candidate} -c 'import semanage'", failonfail: false).exitstatus.zero? @@ -44,7 +47,7 @@ def self.python_command # current file path is lib/puppet/provider/selinux_port/semanage.rb # semanage_ports.py is lib/puppet_x/voxpupuli/selinux/semanage_ports.py - PORTS_HELPER = File.expand_path('../../../../puppet_x/voxpupuli/selinux/semanage_ports.py', __FILE__) + PORTS_HELPER = File.expand_path('../../../puppet_x/voxpupuli/selinux/semanage_ports.py', __dir__) commands semanage: 'semanage', python: python_command @@ -100,14 +103,14 @@ def self.prefetch(resources) instances.each do |provider| resource = resources[provider.name] if resource - unless resource[:low_port].to_s == provider.low_port && resource[:high_port].to_s == provider.high_port && resource[:protocol] == provider.protocol || resource.purging? - raise Puppet::ResourceError, "Selinux_port['#{resource[:name]}']: title does not match its port and protocol, and a conflicting resource exists" - end + raise Puppet::ResourceError, "Selinux_port['#{resource[:name]}']: title does not match its port and protocol, and a conflicting resource exists" unless (resource[:low_port].to_s == provider.low_port && resource[:high_port].to_s == provider.high_port && resource[:protocol] == provider.protocol) || resource.purging? + resource.provider = provider resource[:ensure] = :present if provider.source == :policy else - resources.values.each do |res| + resources.each_value do |res| next unless res[:low_port] == provider.low_port && res[:high_port] == provider.high_port && res[:protocol] == provider.protocol + warning("Selinux_port['#{resource[:name]}']: title does not match format protocol_port") resource.provider = provider resource[:ensure] = :present if provider.source == :policy diff --git a/lib/puppet/type/selinux_fcontext.rb b/lib/puppet/type/selinux_fcontext.rb index 844177bb..dfad0a6b 100644 --- a/lib/puppet/type/selinux_fcontext.rb +++ b/lib/puppet/type/selinux_fcontext.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:selinux_fcontext) do @doc = 'Manage SELinux fcontext definitions. You should use selinux::fcontext instead of this directly.' @@ -46,13 +48,13 @@ end autorequire(:package) do - [ - 'policycoreutils', - 'policycoreutils-python', - 'policycoreutils-python-utils', - 'python3-policycoreutils', - 'selinux-policy-dev', - 'selinux-policy-devel' + %w[ + policycoreutils + policycoreutils-python + policycoreutils-python-utils + python3-policycoreutils + selinux-policy-dev + selinux-policy-devel ] end end diff --git a/lib/puppet/type/selinux_fcontext_equivalence.rb b/lib/puppet/type/selinux_fcontext_equivalence.rb index 3192b755..63b2e2cd 100644 --- a/lib/puppet/type/selinux_fcontext_equivalence.rb +++ b/lib/puppet/type/selinux_fcontext_equivalence.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'pathname' Puppet::Type.newtype(:selinux_fcontext_equivalence) do @@ -10,9 +12,7 @@ newparam(:path, namevar: true) do desc 'The path to set equivalence for' validate do |value| - unless Pathname.new(value).absolute? - raise ArgumentError, "An fcontext equivalence must specify an absolute path instead of '#{value}'" - end + raise ArgumentError, "An fcontext equivalence must specify an absolute path instead of '#{value}'" unless Pathname.new(value).absolute? end end @@ -20,20 +20,18 @@ desc 'The target of the equivalence. ie. the path that this resource will be equivalent to' isrequired validate do |value| - unless Pathname.new(value).absolute? - raise ArgumentError, "The fcontext equivalence target must be an absolute path instead of '#{value}'" - end + raise ArgumentError, "The fcontext equivalence target must be an absolute path instead of '#{value}'" unless Pathname.new(value).absolute? end end autorequire(:package) do - [ - 'policycoreutils', - 'policycoreutils-python', - 'policycoreutils-python-utils', - 'python3-policycoreutils', - 'selinux-policy-dev', - 'selinux-policy-devel' + %w[ + policycoreutils + policycoreutils-python + policycoreutils-python-utils + python3-policycoreutils + selinux-policy-dev + selinux-policy-devel ] end end diff --git a/lib/puppet/type/selinux_login.rb b/lib/puppet/type/selinux_login.rb index 03720668..9f7e94ce 100644 --- a/lib/puppet/type/selinux_login.rb +++ b/lib/puppet/type/selinux_login.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:selinux_login) do @doc = 'Manage SELinux login definitions. You should use selinux::login instead of this directly.' @@ -18,13 +20,13 @@ end autorequire(:package) do - [ - 'policycoreutils', - 'policycoreutils-python', - 'policycoreutils-python-utils', - 'python3-policycoreutils', - 'selinux-policy-dev', - 'selinux-policy-devel' + %w[ + policycoreutils + policycoreutils-python + policycoreutils-python-utils + python3-policycoreutils + selinux-policy-dev + selinux-policy-devel ] end end diff --git a/lib/puppet/type/selinux_permissive.rb b/lib/puppet/type/selinux_permissive.rb index ccd35011..91e85b6c 100644 --- a/lib/puppet/type/selinux_permissive.rb +++ b/lib/puppet/type/selinux_permissive.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:selinux_permissive) do @doc = 'Manage SELinux permissive types.' @@ -14,13 +16,13 @@ end autorequire(:package) do - [ - 'policycoreutils', - 'policycoreutils-python', - 'policycoreutils-python-utils', - 'python3-policycoreutils', - 'selinux-policy-dev', - 'selinux-policy-devel' + %w[ + policycoreutils + policycoreutils-python + policycoreutils-python-utils + python3-policycoreutils + selinux-policy-dev + selinux-policy-devel ] end end diff --git a/lib/puppet/type/selinux_port.rb b/lib/puppet/type/selinux_port.rb index 734095d7..0ae0a1fd 100644 --- a/lib/puppet/type/selinux_port.rb +++ b/lib/puppet/type/selinux_port.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Puppet::Type.newtype(:selinux_port) do @doc = 'Manage SELinux port definitions. You should use selinux::port instead of this directly.' @@ -13,9 +15,7 @@ validate do |val| val = Integer(val) - if val < 1 || val > 65_535 - raise ArgumentError, "Illegal port value '#{val}'" - end + raise ArgumentError, "Illegal port value '#{val}'" if val < 1 || val > 65_535 end end @@ -25,9 +25,7 @@ validate do |val| val = Integer(val) - if val < 1 || val > 65_535 - raise ArgumentError, "Illegal port value '#{val}'" - end + raise ArgumentError, "Illegal port value '#{val}'" if val < 1 || val > 65_535 end end @@ -51,13 +49,13 @@ end autorequire(:package) do - [ - 'policycoreutils', - 'policycoreutils-python', - 'policycoreutils-python-utils', - 'python3-policycoreutils', - 'selinux-policy-dev', - 'selinux-policy-devel' + %w[ + policycoreutils + policycoreutils-python + policycoreutils-python-utils + python3-policycoreutils + selinux-policy-dev + selinux-policy-devel ] end end diff --git a/manifests/config.pp b/manifests/config.pp index 8f095250..4032b4c5 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -8,8 +8,8 @@ # @api private # class selinux::config ( - $mode, - $type, + Optional[Enum['enforcing', 'permissive', 'disabled']] $mode = undef, + Optional[Enum['targeted', 'minimum', 'mls']] $type = undef, ) { assert_private() diff --git a/manifests/refpolicy_package.pp b/manifests/refpolicy_package.pp index 61d0cb66..4dfacd17 100644 --- a/manifests/refpolicy_package.pp +++ b/manifests/refpolicy_package.pp @@ -6,8 +6,8 @@ # @api private # class selinux::refpolicy_package ( - $manage_package = $selinux::manage_package, - $package_name = $selinux::refpolicy_package_name, + Boolean $manage_package = $selinux::manage_package, + String[1] $package_name = $selinux::refpolicy_package_name, ) inherits selinux { assert_private() if $manage_package { diff --git a/spec/acceptance/class_disabled_spec.rb b/spec/acceptance/class_disabled_spec.rb index db308585..b5d48eca 100644 --- a/spec/acceptance/class_disabled_spec.rb +++ b/spec/acceptance/class_disabled_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'selinux class - mode switching' do @@ -9,14 +11,14 @@ # On Debian, SELinux is disabled by default. This first step brings it up to # par with EL and exercises the Debian-specific code. context 'when switching from unknown mode to permissive' do - let(:pp) do + let(:manifest) do <<-EOS class { 'selinux': mode => 'permissive' } EOS end context 'before reboot' do - it_behaves_like 'a idempotent resource' + it_behaves_like 'an idempotent resource' describe package(policy_package_for(hosts)) do it { is_expected.to be_installed } @@ -55,7 +57,7 @@ class { 'selinux': mode => 'disabled' } shell('setenforce Enforcing && test "$(getenforce)" = "Enforcing"') end - it_behaves_like 'a idempotent resource' + it_behaves_like 'an idempotent resource' describe file('/etc/selinux/config') do its(:content) { is_expected.to match(%r{^SELINUX=disabled$}) } @@ -93,14 +95,14 @@ class { 'selinux': mode => 'disabled' } end context 'when switching from disabled to permissive' do - let(:pp) do + let(:manifest) do <<-EOS class { 'selinux': mode => 'permissive' } EOS end context 'before reboot' do - it_behaves_like 'a idempotent resource' + it_behaves_like 'an idempotent resource' describe file('/etc/selinux/config') do its(:content) { is_expected.to match(%r{^SELINUX=permissive$}) } diff --git a/spec/acceptance/class_spec.rb b/spec/acceptance/class_spec.rb index 15ea1058..4e06ff5a 100644 --- a/spec/acceptance/class_spec.rb +++ b/spec/acceptance/class_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'selinux class' do @@ -5,7 +7,7 @@ ensure_permissive_mode_on(hosts) end - let(:pp) do + let(:manifest) do <<-EOS $have_selinux_ruby_library = #{have_selinux_ruby_library(hosts) ? 'true' : 'false'} @@ -103,7 +105,7 @@ class file { read getattr }; # We should really add something for it to purge, but we can't because # semanage doesn't even exist at the start. maybe a separate spec run after this? - it_behaves_like 'a idempotent resource' + it_behaves_like 'an idempotent resource' describe package(policy_package_for(hosts)) do it { is_expected.to be_installed } @@ -121,6 +123,7 @@ class file { read getattr }; describe command('semodule -l | grep puppet_selinux_test_policy') do its(:stdout) { is_expected.to match(%r{puppet_selinux_test_policy}) } end + describe command('semodule -l | grep puppet_selinux_simple_policy') do its(:stdout) { is_expected.to match(%r{puppet_selinux_simple_policy}) } end diff --git a/spec/acceptance/selinux_module_refpolicy_spec.rb b/spec/acceptance/selinux_module_refpolicy_spec.rb index c61dea35..676c9848 100644 --- a/spec/acceptance/selinux_module_refpolicy_spec.rb +++ b/spec/acceptance/selinux_module_refpolicy_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' # @@ -10,7 +12,7 @@ ensure_permissive_mode_on(hosts) end - let(:pp) do + let(:manifest) do <<-EOS class { 'selinux': } @@ -60,5 +62,5 @@ class { 'selinux': } EOS end - it_behaves_like 'a idempotent resource' + it_behaves_like 'an idempotent resource' end diff --git a/spec/acceptance/selinux_permissive_spec.rb b/spec/acceptance/selinux_permissive_spec.rb index 7b35055a..d06873f3 100644 --- a/spec/acceptance/selinux_permissive_spec.rb +++ b/spec/acceptance/selinux_permissive_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'selinux::permissive define', requires_selinux_ruby_library: true do @@ -15,17 +17,21 @@ # cleanup shell('semanage permissive -d passwd_t', acceptable_exit_codes: [0, 1]) end + it 'runs without errors' do expect(result.exit_code).to eq 2 end + it 'makes passwd_t permissive' do shell('semanage permissive -l | grep -q passwd_t') end end + context 'purge with ensure present for passwd_t, when kernel_t is permissive' do before :all do shell('semanage permissive -a kernel_t') end + let(:result) do manifest = <<-EOS selinux::permissive {'passwd_t':} @@ -39,21 +45,26 @@ shell('semanage permissive -d passwd_t', acceptable_exit_codes: [0, 1]) shell('semanage permissive -d kernel_t', acceptable_exit_codes: [0, 1]) end + it 'runs without errors' do expect(result.exit_code).to eq 2 end + it 'purges kernel_t' do shell('semanage permissive -l | grep -q kernel_t', acceptable_exit_codes: [1]) end + it 'makes passwd_t permissive' do shell('semanage permissive -l | grep -q passwd_t') end end + context 'ensure absent for kernel_t only, when passwd_t is also permissive' do before :all do shell('semanage permissive -a kernel_t') shell('semanage permissive -a passwd_t') end + let(:result) do manifest = "selinux::permissive {'kernel_t': ensure => 'absent'}" apply_manifest(manifest, catch_failures: true) @@ -64,12 +75,15 @@ shell('semanage permissive -d passwd_t', acceptable_exit_codes: [0, 1]) shell('semanage permissive -d kernel_t', acceptable_exit_codes: [0, 1]) end + it 'runs without errors' do expect(result.exit_code).to eq 2 end + it 'makes kernel_t not permissive' do shell('semanage permissive -l | grep -q kernel_t', acceptable_exit_codes: [1]) end + it 'does not remove passwd_t' do shell('semanage permissive -l | grep -q passwd_t') end diff --git a/spec/classes/selinux_build_spec.rb b/spec/classes/selinux_build_spec.rb index f22cfe1b..9fc3d545 100644 --- a/spec/classes/selinux_build_spec.rb +++ b/spec/classes/selinux_build_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux::build' do diff --git a/spec/classes/selinux_config_mode_spec.rb b/spec/classes/selinux_config_mode_spec.rb index 60520ab6..2503821d 100644 --- a/spec/classes/selinux_config_mode_spec.rb +++ b/spec/classes/selinux_config_mode_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux' do diff --git a/spec/classes/selinux_config_type_spec.rb b/spec/classes/selinux_config_type_spec.rb index 9ae403d4..51b27701 100755 --- a/spec/classes/selinux_config_type_spec.rb +++ b/spec/classes/selinux_config_type_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux' do @@ -13,6 +15,7 @@ it { is_expected.to compile.and_raise_error(%r{Enum}) } end + context 'undef type' do it { is_expected.to have_file_resource_count(0) } it { is_expected.to have_file_line_resource_count(0) } @@ -21,11 +24,13 @@ it { is_expected.not_to contain_file_line('set-selinux-config-type-to-minimum') } it { is_expected.not_to contain_file_line('set-selinux-config-type-to-mls') } end + context 'targeted' do let(:params) { { type: 'targeted' } } it { is_expected.to contain_file_line('set-selinux-config-type-to-targeted').with(line: 'SELINUXTYPE=targeted') } end + context 'minimum' do let(:params) { { type: 'minimum' } } diff --git a/spec/classes/selinux_package_spec.rb b/spec/classes/selinux_package_spec.rb index f0c5d7ed..48390302 100644 --- a/spec/classes/selinux_package_spec.rb +++ b/spec/classes/selinux_package_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux' do diff --git a/spec/defines/selinux_boolean_spec.rb b/spec/defines/selinux_boolean_spec.rb index 00e2d567..8e1966ea 100644 --- a/spec/defines/selinux_boolean_spec.rb +++ b/spec/defines/selinux_boolean_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux::boolean' do diff --git a/spec/defines/selinux_exec_restorecon_spec.rb b/spec/defines/selinux_exec_restorecon_spec.rb index f3188bfb..bcf04abe 100644 --- a/spec/defines/selinux_exec_restorecon_spec.rb +++ b/spec/defines/selinux_exec_restorecon_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux::exec_restorecon' do @@ -13,25 +15,30 @@ context 'with defaults' do it { is_expected.to contain_exec('selinux::exec_restorecon /opt/mycustompath').with(command: 'restorecon -R /opt/mycustompath', refreshonly: true) } end + context 'without recursion' do let(:params) { { recurse: false } } it { is_expected.to contain_exec('selinux::exec_restorecon /opt/mycustompath').with(command: 'restorecon /opt/mycustompath') } end + context 'with force' do let(:params) { { force: true } } it { is_expected.to contain_exec('selinux::exec_restorecon /opt/mycustompath').with(command: 'restorecon -F -R /opt/mycustompath') } end + context 'with force, without recursion' do let(:params) { { force: true, recurse: false } } it { is_expected.to contain_exec('selinux::exec_restorecon /opt/mycustompath').with(command: 'restorecon -F /opt/mycustompath') } end + context 'ordering' do it { is_expected.to contain_exec('selinux::exec_restorecon /opt/mycustompath').that_comes_before('Anchor[selinux::end]') } it { is_expected.to contain_anchor('selinux::module post').that_comes_before('Exec[selinux::exec_restorecon /opt/mycustompath]') } end + context 'with optional parameters' do let(:params) { { onlyif: 'some_command', unless: 'some_other_command', refreshonly: false } } @@ -44,6 +51,7 @@ end end end + context 'with resource titled /opt/$HOME/some weird dir/' do let(:title) { '/opt/$HOME/some weird dir/' } @@ -51,6 +59,7 @@ it { is_expected.to contain_exec('selinux::exec_restorecon /opt/$HOME/some weird dir/').with(command: "restorecon -R '/opt/$HOME/some weird dir/'", refreshonly: true) } end end + context 'with path /weird/\'pa th\'/"quotes"' do let(:title) { 'just_for_testing' } let(:params) { { path: %q(/weird/'pa th'/"quotes") } } diff --git a/spec/defines/selinux_fcontext_spec.rb b/spec/defines/selinux_fcontext_spec.rb index 65bebb3a..e62f7b05 100644 --- a/spec/defines/selinux_fcontext_spec.rb +++ b/spec/defines/selinux_fcontext_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux::fcontext' do @@ -20,6 +22,7 @@ it { is_expected.to contain_selinux__fcontext('myfile').that_requires('Anchor[selinux::module post]') } it { is_expected.to contain_selinux__fcontext('myfile').that_comes_before('Anchor[selinux::end]') } end + context 'removal ordering' do let(:params) do { @@ -45,6 +48,7 @@ it { is_expected.to compile.and_raise_error(%r{"filetype" must be one of: a,f,d,c,b,s,l,p - see "man semanage-fcontext"}) } end + context 'invalid multiple filetype' do let(:params) do { @@ -56,6 +60,7 @@ it { is_expected.to compile.and_raise_error(%r{"filetype" must be one of: a,f,d,c,b,s,l,p - see "man semanage-fcontext"}) } end + context 'set filemode and context' do let(:params) do { @@ -67,6 +72,7 @@ it { is_expected.to contain_selinux_fcontext('/tmp/file1_a').with(pathspec: '/tmp/file1', seltype: 'user_home_dir_t', file_type: 'a') } end + context 'set context' do let(:params) do { diff --git a/spec/defines/selinux_port_spec.rb b/spec/defines/selinux_port_spec.rb index 7e164d66..815417ac 100644 --- a/spec/defines/selinux_port_spec.rb +++ b/spec/defines/selinux_port_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'selinux::port' do @@ -34,6 +36,7 @@ it { is_expected.to contain_selinux_port("#{protocol}_8080-8080").with(seltype: 'http_port_t') } end + context "protocol #{protocol} and port_range" do let(:params) do { diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 13da4ce5..a489d4f8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Managed by modulesync - DO NOT EDIT # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ @@ -7,15 +9,15 @@ # puppetlabs_spec_helper will set up coverage if the env variable is set. # We want to do this if lib exists and it hasn't been explicitly set. -ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../../lib', __FILE__)) +ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../lib', __dir__)) require 'voxpupuli/test/spec_helper' +add_mocked_facts! + if File.exist?(File.join(__dir__, 'default_module_facts.yml')) facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) - if facts - facts.each do |name, value| - add_custom_fact name.to_sym, value - end + facts&.each do |name, value| + add_custom_fact name.to_sym, value end end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 7037ee7d..42ecdb41 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,71 +1,7 @@ -require 'beaker-rspec' -require 'beaker-puppet' -require 'beaker/puppet_install_helper' -require 'beaker/module_install_helper' +# frozen_string_literal: true -def policy_package_for(hosts) - case hosts[0]['platform'] - when %r{^debian} - 'selinux-policy-default' - else - 'selinux-policy-targeted' - end -end +require 'voxpupuli/acceptance/spec_helper_acceptance' -def have_selinux_ruby_library(hosts) - hosts[0]['platform'] !~ %r{^debian} -end +configure_beaker -run_puppet_install_helper unless ENV['BEAKER_provision'] == 'no' - -RSpec.configure do |c| - # Readable test descriptions - c.formatter = :documentation - - # Configure all nodes in nodeset - c.before :suite do - install_module - install_module_dependencies - - # Relabelling fails because systemd tries to connect the script's STDIN to - # a serial port that doesn't exist (in Vagrant, at least). Work around like - # in https://bugs.centos.org/view.php?id=13213 - hosts.each do |host| - next unless host['platform'] =~ %r{^el-7} - - on host, 'sed -i -e "s/console=tty0 console=ttyS0,115200/console=tty0/" /etc/default/grub' - on host, 'cat /etc/default/grub' - on host, 'grub2-mkconfig -o /boot/grub2/grub.cfg' - end - end - - unless have_selinux_ruby_library(hosts) - c.filter_run_excluding requires_selinux_ruby_library: true - end -end - -shared_examples 'a idempotent resource' do - it 'applies with no errors' do - apply_manifest(pp, catch_failures: true) - end - - it 'applies a second time without changes' do - apply_manifest(pp, catch_changes: true) - end -end - -def ensure_permissive_mode_on(hosts) - hosts.each do |host| - host.execute('getenforce') do |result| - mode = result.stdout.strip - if mode != 'Permissive' - host.execute('sed -i "s/SELINUX=.*/SELINUX=permissive/" /etc/selinux/config') - if mode == 'Disabled' - host.reboot - else - host.execute('setenforce Permissive && test "$(getenforce)" = "Permissive"') - end - end - end - end -end +Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } diff --git a/spec/support/acceptance/helper_methods.rb b/spec/support/acceptance/helper_methods.rb new file mode 100644 index 00000000..222e3afc --- /dev/null +++ b/spec/support/acceptance/helper_methods.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +def policy_package_for(hosts) + case hosts[0]['platform'] + when %r{^debian} + 'selinux-policy-default' + else + 'selinux-policy-targeted' + end +end + +def have_selinux_ruby_library(hosts) + hosts[0]['platform'] !~ %r{^debian} +end + +def ensure_permissive_mode_on(hosts) + hosts.each do |host| + host.execute('getenforce') do |result| + mode = result.stdout.strip + if mode != 'Permissive' + host.execute('sed -i "s/SELINUX=.*/SELINUX=permissive/" /etc/selinux/config') + if mode == 'Disabled' + host.reboot + else + host.execute('setenforce Permissive && test "$(getenforce)" = "Permissive"') + end + end + end + end +end diff --git a/spec/unit/provider/selinux_port/semanage_spec.rb b/spec/unit/provider/selinux_port/semanage_spec.rb index 8d1d1681..f786c80f 100644 --- a/spec/unit/provider/selinux_port/semanage_spec.rb +++ b/spec/unit/provider/selinux_port/semanage_spec.rb @@ -1,33 +1,35 @@ +# frozen_string_literal: true + require 'spec_helper' semanage_provider = Puppet::Type.type(:selinux_port).provider(:semanage) port = Puppet::Type.type(:selinux_port) # 23 lines: -ports_helper_output = <<-EOS -policy system_u:object_r:ipp_port_t:s0 8614 8610 tcp -policy system_u:object_r:ipp_port_t:s0 8614 8610 udp -policy system_u:object_r:pki_ca_port_t:s0 9447 9443 tcp -policy system_u:object_r:gluster_port_t:s0 38469 38465 tcp -policy system_u:object_r:http_cache_port_t:s0 10010 10001 tcp -policy system_u:object_r:traceroute_port_t:s0 64010 64000 udp -policy system_u:object_r:vnc_port_t:s0 5999 5985 tcp -policy system_u:object_r:cyphesis_port_t:s0 6799 6780 tcp -policy system_u:object_r:xserver_port_t:s0 6020 6000 tcp -policy system_u:object_r:gluster_port_t:s0 24027 24007 tcp -policy system_u:object_r:mysqld_port_t:s0 63164 63132 tcp -policy system_u:object_r:virt_migration_port_t:s0 49216 49152 tcp -policy system_u:object_r:vnc_port_t:s0 5983 5900 tcp -policy system_u:object_r:unreserved_port_t:s0 65535 61001 tcp -policy system_u:object_r:unreserved_port_t:s0 65535 61001 udp -policy system_u:object_r:ephemeral_port_t:s0 61000 32768 tcp -policy system_u:object_r:ephemeral_port_t:s0 61000 32768 udp -policy system_u:object_r:unreserved_port_t:s0 32767 1024 tcp -policy system_u:object_r:unreserved_port_t:s0 32767 1024 udp -local system_u:object_r:zope_port_t:s0 12345 12345 tcp -local system_u:object_r:zope_port_t:s0 12345 12345 udp -local system_u:object_r:zookeeper_client_port_t:s0 15132 15123 udp -local system_u:object_r:zookeeper_client_port_t:s0 15132 15123 tcp +ports_helper_output = <<~EOS + policy system_u:object_r:ipp_port_t:s0 8614 8610 tcp + policy system_u:object_r:ipp_port_t:s0 8614 8610 udp + policy system_u:object_r:pki_ca_port_t:s0 9447 9443 tcp + policy system_u:object_r:gluster_port_t:s0 38469 38465 tcp + policy system_u:object_r:http_cache_port_t:s0 10010 10001 tcp + policy system_u:object_r:traceroute_port_t:s0 64010 64000 udp + policy system_u:object_r:vnc_port_t:s0 5999 5985 tcp + policy system_u:object_r:cyphesis_port_t:s0 6799 6780 tcp + policy system_u:object_r:xserver_port_t:s0 6020 6000 tcp + policy system_u:object_r:gluster_port_t:s0 24027 24007 tcp + policy system_u:object_r:mysqld_port_t:s0 63164 63132 tcp + policy system_u:object_r:virt_migration_port_t:s0 49216 49152 tcp + policy system_u:object_r:vnc_port_t:s0 5983 5900 tcp + policy system_u:object_r:unreserved_port_t:s0 65535 61001 tcp + policy system_u:object_r:unreserved_port_t:s0 65535 61001 udp + policy system_u:object_r:ephemeral_port_t:s0 61000 32768 tcp + policy system_u:object_r:ephemeral_port_t:s0 61000 32768 udp + policy system_u:object_r:unreserved_port_t:s0 32767 1024 tcp + policy system_u:object_r:unreserved_port_t:s0 32767 1024 udp + local system_u:object_r:zope_port_t:s0 12345 12345 tcp + local system_u:object_r:zope_port_t:s0 12345 12345 udp + local system_u:object_r:zookeeper_client_port_t:s0 15132 15123 udp + local system_u:object_r:zookeeper_client_port_t:s0 15132 15123 tcp EOS # END 23 instances @@ -92,15 +94,18 @@ # Call to python helper script semanage_provider.expects(:python).returns(ports_helper_output) end + it 'returns 23 resources' do expect(described_class.instances.size).to eq(23) end + instance_examples.each do |index, hash| it "parses example #{index} correctly" do expect(described_class.instances[index].instance_variable_get('@property_hash')).to eq(hash) end end end + context 'creating' do let(:resource) do res = port.new(resource_example) @@ -112,12 +117,14 @@ described_class.expects(:semanage).with('port', '-a', '-t', 'zookeeper_client_port_t', '-p', :tcp, '15123-15132') resource.provider.create end + it 'runs semanage port -a for a single port' do resource[:high_port] = resource[:low_port] described_class.expects(:semanage).with('port', '-a', '-t', 'zookeeper_client_port_t', '-p', :tcp, '15123') resource.provider.create end end + context 'deleting' do let(:res_port_range) do res = port.new(resource_example) @@ -136,11 +143,13 @@ described_class.expects(:semanage).with('port', '-d', '-p', :tcp, '15123-15132') res_port_range.provider.destroy end + it 'runs semanage port -d for a single port' do described_class.expects(:semanage).with('port', '-d', '-p', :tcp, '15123') res_single_port.provider.destroy end end + context 'with resources differing from the catalog' do let(:resources) do { @@ -160,6 +169,7 @@ semanage_provider.expects(:python).returns(ports_helper_output) semanage_provider.prefetch(resources) end + context 'prefetch finds the provider for tcp_15123-15132 (resource example)' do let(:p) { resources['tcp_15123-15132'].provider } diff --git a/spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb b/spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb index 3d83c8ea..0a66318d 100644 --- a/spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb +++ b/spec/unit/puppet/provider/selinux_fcontext/semanage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' # stub the selinux module for tests in travis @@ -14,19 +16,19 @@ def selinux_file_context_path semanage_provider = Puppet::Type.type(:selinux_fcontext).provider(:semanage) fcontext = Puppet::Type.type(:selinux_fcontext) -fcontexts_local = <<-EOS -# This file is auto-generated by libsemanage -# Do not edit directly. +fcontexts_local = <<~EOS + # This file is auto-generated by libsemanage + # Do not edit directly. -/foobar system_u:object_r:bin_t:s0 -/tmp/foobar -d system_u:object_r:boot_t:s0 -/something/else -s <> + /foobar system_u:object_r:bin_t:s0 + /tmp/foobar -d system_u:object_r:boot_t:s0 + /something/else -s <> EOS -fcontexts_system = <<-EOS -# This file is auto-generated by libsemanage -# Do not edit directly. -/var/log system_u:object_r:var_log_t:s0 +fcontexts_system = <<~EOS + # This file is auto-generated by libsemanage + # Do not edit directly. + /var/log system_u:object_r:var_log_t:s0 EOS describe semanage_provider do @@ -42,9 +44,11 @@ def selinux_file_context_path File.expects(:exist?).with('spec_dummy').returns(true) File.expects(:readlines).with('spec_dummy').returns(fcontexts_local.split("\n")) end + it 'returns three resources' do expect(described_class.instances.size).to eq(3) end + it 'regular contexts get parsed properly' do expect(described_class.instances[0].instance_variable_get('@property_hash')).to eq( ensure: :present, @@ -57,6 +61,7 @@ def selinux_file_context_path selrange: 's0' ) end + it '<> contexts get parsed properly' do expect(described_class.instances[2].instance_variable_get('@property_hash')).to eq( ensure: :present, @@ -70,15 +75,18 @@ def selinux_file_context_path ) end end + context 'with no fcontexts defined, and no fcontexts.local file' do before do Selinux.expects(:selinux_file_context_local_path).returns('spec_dummy') File.expects(:exist?).with('spec_dummy').returns(false) end + it 'returns no resources' do expect(described_class.instances.size).to eq(0) end end + context 'Creating with just seltype defined' do let(:resource) do res = fcontext.new(name: '/something(/.*)_a', file_type: 'a', seltype: 'some_type_t', ensure: :present, pathspec: '/something(/.*)') @@ -86,21 +94,23 @@ def selinux_file_context_path res end - it 'runs semanage fcontext -a ' do + it 'runs semanage fcontext -a' do described_class.expects(:semanage).with('fcontext', '-a', '-t', 'some_type_t', '-f', 'a', '/something(/.*)') resource.provider.create end end + context 'Deleting with just seltype defined' do let(:provider) do semanage_provider.new(name: '/something(/.*)_a', file_type: 'a', seltype: 'some_type_t', ensure: :present, pathspec: '/something(/.*)') end - it 'runs semanage fcontext -d ' do + it 'runs semanage fcontext -d' do described_class.expects(:semanage).with('fcontext', '-d', '-t', 'some_type_t', '-f', 'a', '/something(/.*)') provider.destroy end end + context 'With resources differing from the catalog' do let(:resources) do return { @@ -134,10 +144,12 @@ def selinux_file_context_path File.expects(:readlines).with('spec_policy_dummy').returns(fcontexts_system.split("\n")) semanage_provider.prefetch(resources) end + it 'finds provider for /foobar' do p = resources['/foobar_a'].provider expect(p).not_to eq(nil) end + context 'has the correct attributes' do let(:p) { resources['/foobar_a'].provider } @@ -147,11 +159,13 @@ def selinux_file_context_path it { expect(p.selrole).to eq('object_r') } it { expect(p.seluser).to eq('system_u') } end + it 'can change seltype' do p = resources['/foobar_a'].provider described_class.expects(:semanage).with('fcontext', '-m', '-t', 'new_type_t', '-f', 'a', '/foobar') p.seltype = 'new_type_t' end + it 'can change seluser' do p = resources['/foobar_a'].provider described_class.expects(:semanage).with('fcontext', '-m', '-s', 'unconfined_u', '-t', 'bin_t', '-f', 'a', '/foobar') @@ -162,6 +176,7 @@ def selinux_file_context_path p = resources['/var/log_a'].provider expect(p).not_to eq(nil) end + context 'has the correct attributes from the system policy' do let(:p) { resources['/var/log_a'].provider } @@ -171,11 +186,13 @@ def selinux_file_context_path it { expect(p.selrole).to eq('object_r') } it { expect(p.seluser).to eq('system_u') } end + it 'can change seltype' do p = resources['/var/log_a'].provider described_class.expects(:semanage).with('fcontext', '-m', '-t', 'new_type_t', '-f', 'a', '/var/log') p.seltype = 'new_type_t' end + it 'can change seluser' do p = resources['/var/log_a'].provider described_class.expects(:semanage).with('fcontext', '-m', '-s', 'unconfined_u', '-t', 'var_log_t', '-f', 'a', '/var/log') diff --git a/spec/unit/puppet/provider/selinux_fcontext_equivalence/semanage_spec.rb b/spec/unit/puppet/provider/selinux_fcontext_equivalence/semanage_spec.rb index 6b61d24e..f2b1e510 100644 --- a/spec/unit/puppet/provider/selinux_fcontext_equivalence/semanage_spec.rb +++ b/spec/unit/puppet/provider/selinux_fcontext_equivalence/semanage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' # Provide a dummy Selinux module for the test @@ -10,10 +12,10 @@ def selinux_file_context_subs_path semanage_provider = Puppet::Type.type(:selinux_fcontext_equivalence).provider(:semanage) fc_equiv = Puppet::Type.type(:selinux_fcontext_equivalence) -fcontext_equivs = <<-EOS -/foobar /var/lib/whatever -/opt/my/other/app /var/lib/whatever -/opt/foo /usr/share/wordpress +fcontext_equivs = <<~EOS + /foobar /var/lib/whatever + /opt/my/other/app /var/lib/whatever + /opt/foo /usr/share/wordpress EOS describe semanage_provider do @@ -29,9 +31,11 @@ def selinux_file_context_subs_path File.expects(:exist?).with('spec_dummy').returns(true) File.expects(:readlines).with('spec_dummy').returns(fcontext_equivs.split("\n")) end + it 'returns three resources' do expect(described_class.instances.size).to eq(3) end + it 'equivalences get parsed properly' do expect(described_class.instances[0].instance_variable_get('@property_hash')).to eq( ensure: :present, @@ -40,15 +44,18 @@ def selinux_file_context_subs_path ) end end + context 'with no equivalences file' do before do Selinux.expects(:selinux_file_context_subs_path).returns('spec_dummy') File.expects(:exist?).with('spec_dummy').returns(false) end + it 'returns no resources' do expect(described_class.instances.size).to eq(0) end end + context 'Creating' do let(:resource) do res = fc_equiv.new(name: '/foobar', ensure: :present, target: '/something') @@ -61,6 +68,7 @@ def selinux_file_context_subs_path resource.provider.create end end + context 'Deleting' do let(:provider) do semanage_provider.new(name: '/foobar', ensure: :present, target: '/something') @@ -71,6 +79,7 @@ def selinux_file_context_subs_path provider.destroy end end + context 'With resources differing from the catalog' do let(:resources) do return { '/opt/myapp' => fc_equiv.new( @@ -90,15 +99,18 @@ def selinux_file_context_subs_path File.expects(:readlines).with('spec_dummy').returns(fcontext_equivs.split("\n")) semanage_provider.prefetch(resources) end + it 'finds provider for /foobar' do p = resources['/foobar'].provider expect(p).not_to eq(nil) end + context 'has the correct target' do let(:p) { resources['/foobar'].provider } it { expect(p.target).to eq('/var/lib/whatever') } end + it 'can change target by doing a non-reloading delete' do p = resources['/foobar'].provider described_class.expects(:semanage).with('fcontext', '-N', '-d', '-e', '/var/lib/whatever', '/foobar') diff --git a/spec/unit/puppet/provider/selinux_permissive/semanage_spec.rb b/spec/unit/puppet/provider/selinux_permissive/semanage_spec.rb index 11770fd3..e3a25f05 100644 --- a/spec/unit/puppet/provider/selinux_permissive/semanage_spec.rb +++ b/spec/unit/puppet/provider/selinux_permissive/semanage_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' semanage_provider = Puppet::Type.type(:selinux_permissive).provider(:semanage) @@ -41,9 +43,11 @@ before do described_class.expects(:semanage).with('permissive', '--list').returns(semanage_output) end + it 'returns one resource' do expect(described_class.instances.size).to eq(1) end + it 'has a name tlp_t and ensure present' do expect(described_class.instances[0].instance_variable_get('@property_hash')).to eq( name: 'tlp_t', @@ -53,36 +57,43 @@ ) end end + context 'With a custom type' do before do described_class.expects(:semanage).with('permissive', '--list').returns(semanage_output_custom) end + it 'returns two resources' do expect(described_class.instances.size).to eq(2) end end end + context 'Creating' do it 'runs semanage permissive -a' do described_class.expects(:semanage).with('permissive', '-a', 'test_t') provider.create end end + context 'Deleting' do it 'runs semanage permissive -d' do described_class.expects(:semanage).with('permissive', '-d', 'test_t') provider.destroy end end + context 'Prefetch' do before do described_class.expects(:semanage).with('permissive', '--list').returns(semanage_output_custom) end + it 'matches the provider' do semanage_provider.prefetch('test_t' => resource, 'tlp_t' => permissive.new(seltype: 'tlp_t', ensure: :present)) expect(resource.provider.exists?).to eq(true) end end + context 'Prefetch when purging' do let(:built_in) do b = permissive.new(seltype: 'tlp_t') diff --git a/spec/unit/puppet/type/selinux_fcontext_equivalence_spec.rb b/spec/unit/puppet/type/selinux_fcontext_equivalence_spec.rb index 2ed00164..45628443 100644 --- a/spec/unit/puppet/type/selinux_fcontext_equivalence_spec.rb +++ b/spec/unit/puppet/type/selinux_fcontext_equivalence_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:selinux_fcontext_equivalence) do @@ -6,6 +8,7 @@ it 'fails with invalid path' do expect { described_class.new(path: 'no_good') }.to raise_error Puppet::ResourceError, %r{must specify an absolute path instead of 'no_good'} end + it 'fails with invalid target path' do expect { described_class.new(path: '/good', target: 'bad_target') }.to raise_error Puppet::ResourceError, %r{must be an absolute path instead of 'bad_target'} end