diff --git a/modules/services/unix/ftp/proftpd/secgen_metadata.xml b/modules/services/unix/ftp/proftpd/secgen_metadata.xml
index 816e8a6b3..2ed398773 100644
--- a/modules/services/unix/ftp/proftpd/secgen_metadata.xml
+++ b/modules/services/unix/ftp/proftpd/secgen_metadata.xml
@@ -34,7 +34,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/utilities/unix/labtainers/secgen_metadata.xml b/modules/utilities/unix/labtainers/secgen_metadata.xml
index 4eb386cd2..8c50399ea 100644
--- a/modules/utilities/unix/labtainers/secgen_metadata.xml
+++ b/modules/utilities/unix/labtainers/secgen_metadata.xml
@@ -42,7 +42,7 @@
.*docker
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/utilities/unix/labtainers_marker/secgen_metadata.xml b/modules/utilities/unix/labtainers_marker/secgen_metadata.xml
index 19a237700..4374e506c 100644
--- a/modules/utilities/unix/labtainers_marker/secgen_metadata.xml
+++ b/modules/utilities/unix/labtainers_marker/secgen_metadata.xml
@@ -50,7 +50,7 @@
.*docker
-->
diff --git a/modules/utilities/unix/system/accounts/CHANGELOG.md b/modules/utilities/unix/system/accounts_legacy/accounts/CHANGELOG.md
similarity index 100%
rename from modules/utilities/unix/system/accounts/CHANGELOG.md
rename to modules/utilities/unix/system/accounts_legacy/accounts/CHANGELOG.md
diff --git a/modules/utilities/unix/system/accounts/CONTRIBUTING.md b/modules/utilities/unix/system/accounts_legacy/accounts/CONTRIBUTING.md
similarity index 100%
rename from modules/utilities/unix/system/accounts/CONTRIBUTING.md
rename to modules/utilities/unix/system/accounts_legacy/accounts/CONTRIBUTING.md
diff --git a/modules/utilities/unix/system/accounts/Gemfile b/modules/utilities/unix/system/accounts_legacy/accounts/Gemfile
similarity index 100%
rename from modules/utilities/unix/system/accounts/Gemfile
rename to modules/utilities/unix/system/accounts_legacy/accounts/Gemfile
diff --git a/modules/utilities/unix/system/accounts/LICENSE b/modules/utilities/unix/system/accounts_legacy/accounts/LICENSE
similarity index 100%
rename from modules/utilities/unix/system/accounts/LICENSE
rename to modules/utilities/unix/system/accounts_legacy/accounts/LICENSE
diff --git a/modules/utilities/unix/system/accounts/NOTICE b/modules/utilities/unix/system/accounts_legacy/accounts/NOTICE
similarity index 100%
rename from modules/utilities/unix/system/accounts/NOTICE
rename to modules/utilities/unix/system/accounts_legacy/accounts/NOTICE
diff --git a/modules/utilities/unix/system/accounts/README.markdown b/modules/utilities/unix/system/accounts_legacy/accounts/README.markdown
similarity index 100%
rename from modules/utilities/unix/system/accounts/README.markdown
rename to modules/utilities/unix/system/accounts_legacy/accounts/README.markdown
diff --git a/modules/utilities/unix/system/accounts/Rakefile b/modules/utilities/unix/system/accounts_legacy/accounts/Rakefile
similarity index 100%
rename from modules/utilities/unix/system/accounts/Rakefile
rename to modules/utilities/unix/system/accounts_legacy/accounts/Rakefile
diff --git a/modules/utilities/unix/system/accounts/accounts.pp b/modules/utilities/unix/system/accounts_legacy/accounts/accounts.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/accounts.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/accounts.pp
diff --git a/modules/utilities/unix/system/accounts/checksums.json b/modules/utilities/unix/system/accounts_legacy/accounts/checksums.json
similarity index 100%
rename from modules/utilities/unix/system/accounts/checksums.json
rename to modules/utilities/unix/system/accounts_legacy/accounts/checksums.json
diff --git a/modules/utilities/unix/system/accounts/examples/user_group.pp b/modules/utilities/unix/system/accounts_legacy/accounts/examples/user_group.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/examples/user_group.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/examples/user_group.pp
diff --git a/modules/utilities/unix/system/accounts/examples/user_group_hash.pp b/modules/utilities/unix/system/accounts_legacy/accounts/examples/user_group_hash.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/examples/user_group_hash.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/examples/user_group_hash.pp
diff --git a/modules/utilities/unix/system/accounts/files/shell/bash_profile b/modules/utilities/unix/system/accounts_legacy/accounts/files/shell/bash_profile
similarity index 100%
rename from modules/utilities/unix/system/accounts/files/shell/bash_profile
rename to modules/utilities/unix/system/accounts_legacy/accounts/files/shell/bash_profile
diff --git a/modules/utilities/unix/system/accounts/files/shell/bashrc b/modules/utilities/unix/system/accounts_legacy/accounts/files/shell/bashrc
similarity index 100%
rename from modules/utilities/unix/system/accounts/files/shell/bashrc
rename to modules/utilities/unix/system/accounts_legacy/accounts/files/shell/bashrc
diff --git a/modules/utilities/unix/system/accounts/manifests/home_dir.pp b/modules/utilities/unix/system/accounts_legacy/accounts/manifests/home_dir.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/manifests/home_dir.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/manifests/home_dir.pp
diff --git a/modules/utilities/unix/system/accounts/manifests/manage_keys.pp b/modules/utilities/unix/system/accounts_legacy/accounts/manifests/manage_keys.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/manifests/manage_keys.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/manifests/manage_keys.pp
diff --git a/modules/utilities/unix/system/accounts/manifests/user.pp b/modules/utilities/unix/system/accounts_legacy/accounts/manifests/user.pp
similarity index 100%
rename from modules/utilities/unix/system/accounts/manifests/user.pp
rename to modules/utilities/unix/system/accounts_legacy/accounts/manifests/user.pp
diff --git a/modules/utilities/unix/system/accounts/metadata.json b/modules/utilities/unix/system/accounts_legacy/accounts/metadata.json
similarity index 100%
rename from modules/utilities/unix/system/accounts/metadata.json
rename to modules/utilities/unix/system/accounts_legacy/accounts/metadata.json
diff --git a/modules/utilities/unix/system/accounts/secgen_metadata.xml b/modules/utilities/unix/system/accounts_legacy/accounts/secgen_metadata.xml
similarity index 81%
rename from modules/utilities/unix/system/accounts/secgen_metadata.xml
rename to modules/utilities/unix/system/accounts_legacy/accounts/secgen_metadata.xml
index 1cb83c269..c5790a1c8 100644
--- a/modules/utilities/unix/system/accounts/secgen_metadata.xml
+++ b/modules/utilities/unix/system/accounts_legacy/accounts/secgen_metadata.xml
@@ -16,4 +16,10 @@
https://forge.puppet.com/puppetlabs/accounts
+
+ .*/bases/.*kali.*
+
+
+ .*/bases/.*buster.*
+
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/centos-7-x64.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/centos-7-x64.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/centos-7-x64.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/centos-7-x64.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/debian-8-x64.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/debian-8-x64.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/debian-8-x64.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/debian-8-x64.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/default.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/default.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/default.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/default.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/centos-7.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/centos-7.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/centos-7.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/centos-7.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/debian-8.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/debian-8.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/debian-8.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/debian-8.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/ubuntu-14.04.yml b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
diff --git a/modules/utilities/unix/system/accounts/spec/acceptance/user_spec.rb b/modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/user_spec.rb
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/acceptance/user_spec.rb
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/acceptance/user_spec.rb
diff --git a/modules/utilities/unix/system/accounts/spec/defines/accounts_user_spec.rb b/modules/utilities/unix/system/accounts_legacy/accounts/spec/defines/accounts_user_spec.rb
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/defines/accounts_user_spec.rb
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/defines/accounts_user_spec.rb
diff --git a/modules/utilities/unix/system/accounts/spec/spec_helper.rb b/modules/utilities/unix/system/accounts_legacy/accounts/spec/spec_helper.rb
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/spec_helper.rb
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/spec_helper.rb
diff --git a/modules/utilities/unix/system/accounts/spec/spec_helper_acceptance.rb b/modules/utilities/unix/system/accounts_legacy/accounts/spec/spec_helper_acceptance.rb
similarity index 100%
rename from modules/utilities/unix/system/accounts/spec/spec_helper_acceptance.rb
rename to modules/utilities/unix/system/accounts_legacy/accounts/spec/spec_helper_acceptance.rb
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/Dockerfile b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/Dockerfile
new file mode 100644
index 000000000..12ed4ff10
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/Dockerfile
@@ -0,0 +1,6 @@
+FROM puppet/pdk:latest
+
+# [Optional] Uncomment this section to install additional packages.
+# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
+# && apt-get -y install --no-install-recommends
+
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/README.md b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/README.md
new file mode 100644
index 000000000..cc4675e5d
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/README.md
@@ -0,0 +1,34 @@
+# devcontainer
+
+
+For format details, see https://aka.ms/devcontainer.json.
+
+For config options, see the README at:
+https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet
+
+``` json
+{
+ "name": "Puppet Development Kit (Community)",
+ "dockerFile": "Dockerfile",
+
+ // Set *default* container specific settings.json values on container create.
+ "settings": {
+ "terminal.integrated.shell.linux": "/bin/bash"
+ },
+
+ // Add the IDs of extensions you want installed when the container is created.
+ "extensions": [
+ "puppet.puppet-vscode",
+ "rebornix.Ruby"
+ ]
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ "forwardPorts": [],
+
+ // Use 'postCreateCommand' to run commands after the container is created.
+ "postCreateCommand": "pdk --version",
+}
+```
+
+
+
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/devcontainer.json b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..fe7a8b12b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.devcontainer/devcontainer.json
@@ -0,0 +1,17 @@
+{
+ "name": "Puppet Development Kit (Community)",
+ "dockerFile": "Dockerfile",
+
+ "settings": {
+ "terminal.integrated.profiles.linux": {
+ "bash": {
+ "path": "bash",
+ }
+ }
+ },
+
+ "extensions": [
+ "puppet.puppet-vscode",
+ "rebornix.Ruby"
+ ]
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.fixtures.yml b/modules/utilities/unix/system/accounts_newer/accounts/.fixtures.yml
new file mode 100644
index 000000000..0a4d5d0dc
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.fixtures.yml
@@ -0,0 +1,13 @@
+fixtures:
+ repositories:
+ sshkeys_core:
+ repo: 'https://github.com/puppetlabs/puppetlabs-sshkeys_core'
+ puppet_version: '>= 6.0.0'
+ stdlib:
+ repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git'
+ ref: '5.0.0'
+ facts: 'https://github.com/puppetlabs/puppetlabs-facts.git'
+ puppet_agent: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git'
+ provision: 'https://github.com/puppetlabs/provision.git'
+ symlinks:
+ accounts: "#{source_dir}"
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.gitattributes b/modules/utilities/unix/system/accounts_newer/accounts/.gitattributes
new file mode 100644
index 000000000..d41f62499
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.gitattributes
@@ -0,0 +1,6 @@
+*.rb eol=lf
+*.erb eol=lf
+*.pp eol=lf
+*.sh eol=lf
+*.epp eol=lf
+files/shell/* eol=lf
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/auto_release.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/auto_release.yml
new file mode 100644
index 000000000..f4aed440e
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/auto_release.yml
@@ -0,0 +1,90 @@
+name: "Auto release"
+
+on:
+ workflow_dispatch:
+
+env:
+ HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
+ HONEYCOMB_DATASET: litmus tests
+ CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+jobs:
+ auto_release:
+ name: "Automatic release prep"
+ runs-on: ubuntu-20.04
+
+ steps:
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+
+ - name: "Honeycomb: start first step"
+ run: |
+ echo STEP_ID="auto-release" >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: "Checkout Source"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+
+ - name: "PDK Release prep"
+ uses: docker://puppet/iac_release:ci
+ with:
+ args: 'release prep --force'
+ env:
+ CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: "Get Version"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ id: gv
+ run: |
+ echo "::set-output name=ver::$(jq --raw-output .version metadata.json)"
+
+ - name: "Check if a release is necessary"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ id: check
+ run: |
+ git diff --quiet CHANGELOG.md && echo "::set-output name=release::false" || echo "::set-output name=release::true"
+
+ - name: "Commit changes"
+ if: ${{ github.repository_owner == 'puppetlabs' && steps.check.outputs.release == 'true' }}
+ run: |
+ git config --local user.email "${{ github.repository_owner }}@users.noreply.github.com"
+ git config --local user.name "GitHub Action"
+ git add .
+ git commit -m "Release prep v${{ steps.gv.outputs.ver }}"
+
+ - name: Create Pull Request
+ id: cpr
+ uses: puppetlabs/peter-evans-create-pull-request@v3
+ if: ${{ github.repository_owner == 'puppetlabs' && steps.check.outputs.release == 'true' }}
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: "Release prep v${{ steps.gv.outputs.ver }}"
+ branch: "release-prep"
+ delete-branch: true
+ title: "Release prep v${{ steps.gv.outputs.ver }}"
+ body: |
+ Automated release-prep through [pdk-templates](https://github.com/puppetlabs/pdk-templates/blob/main/moduleroot/.github/workflows/auto_release.yml.erb) from commit ${{ github.sha }}.
+ Please verify before merging:
+ - [ ] last [nightly](https://github.com/${{ github.repository }}/actions/workflows/nightly.yml) run is green
+ - [ ] [Changelog](https://github.com/${{ github.repository }}/blob/release-prep/CHANGELOG.md) is readable and has no unlabeled pull requests
+ - [ ] Ensure the [changelog](https://github.com/${{ github.repository }}/blob/release-prep/CHANGELOG.md) version and [metadata](https://github.com/${{ github.repository }}/blob/release-prep/metadata.json) version match
+ labels: "maintenance"
+
+ - name: PR outputs
+ if: ${{ github.repository_owner == 'puppetlabs' && steps.check.outputs.release == 'true' }}
+ run: |
+ echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
+ echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
+
+ - name: "Honeycomb: Record finish step"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Finished auto release workflow'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/labeller.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/labeller.yml
new file mode 100644
index 000000000..5434d3fff
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/labeller.yml
@@ -0,0 +1,22 @@
+name: community-labeller
+
+on:
+ issues:
+ types:
+ - opened
+ pull_request_target:
+ types:
+ - opened
+
+jobs:
+ label:
+ runs-on: ubuntu-latest
+ steps:
+
+ - uses: puppetlabs/community-labeller@v0
+ name: Label issues or pull requests
+ with:
+ label_name: community
+ label_color: '5319e7'
+ org_membership: puppetlabs
+ token: ${{ secrets.IAC_COMMUNITY_LABELER }}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/nightly.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/nightly.yml
new file mode 100644
index 000000000..42816e7de
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/nightly.yml
@@ -0,0 +1,204 @@
+name: "nightly"
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+
+
+env:
+ HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
+ HONEYCOMB_DATASET: litmus tests
+
+jobs:
+ setup_matrix:
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ name: "Setup Test Matrix"
+ runs-on: ubuntu-20.04
+ outputs:
+ matrix: ${{ steps.get-matrix.outputs.matrix }}
+
+ steps:
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+
+ - name: "Honeycomb: Start first step"
+ run: |
+ echo STEP_ID=setup-environment >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Checkout Source
+ uses: actions/checkout@v2
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+
+ - name: Activate Ruby 2.7
+ uses: ruby/setup-ruby@v1
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ with:
+ ruby-version: "2.7"
+ bundler-cache: true
+
+ - name: Print bundle environment
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+
+ - name: "Honeycomb: Record Setup Environment time"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Environment'
+ echo STEP_ID=Setup-Acceptance-Test-Matrix >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Setup Acceptance Test Matrix
+ id: get-matrix
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ if [ '${{ github.repository_owner }}' == 'puppetlabs' ]; then
+ buildevents cmd $TRACE_ID $STEP_ID matrix_from_metadata -- bundle exec matrix_from_metadata_v2
+ else
+ echo "::set-output name=matrix::{}"
+ fi
+
+ - name: "Honeycomb: Record Setup Test Matrix time"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Test Matrix'
+ Acceptance:
+ name: "${{matrix.platforms.label}}, ${{matrix.collection}}"
+ needs:
+ - setup_matrix
+
+ runs-on: ubuntu-20.04
+ strategy:
+ fail-fast: false
+ matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}}
+
+ env:
+ BUILDEVENT_FILE: '../buildevents.txt'
+
+ steps:
+ - run: |
+ echo 'platform=${{ matrix.platforms.image }}' >> $BUILDEVENT_FILE
+ echo 'collection=${{ matrix.collection }}' >> $BUILDEVENT_FILE
+ echo 'label=${{ matrix.platforms.label }}' >> $BUILDEVENT_FILE
+
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+ matrix-key: ${{ matrix.platforms.label }}-${{ matrix.collection }}
+
+ - name: "Honeycomb: start first step"
+ run: |
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-1 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+
+ - name: Checkout Source
+ uses: actions/checkout@v2
+
+ - name: Activate Ruby 2.7
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "2.7"
+ bundler-cache: true
+
+ - name: Print bundle environment
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+
+ - name: "Honeycomb: Record Setup Environment time"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Environment'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-2 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+
+ - name: Provision test environment
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:provision ${{ matrix.platforms.image }}' -- bundle exec rake 'litmus:provision[${{matrix.platforms.provider}},${{ matrix.platforms.image }}]'
+ echo ::group::=== REQUEST ===
+ cat request.json || true
+ echo
+ echo ::endgroup::
+ echo ::group::=== INVENTORY ===
+ if [ -f 'spec/fixtures/litmus_inventory.yaml' ];
+ then
+ FILE='spec/fixtures/litmus_inventory.yaml'
+ elif [ -f 'inventory.yaml' ];
+ then
+ FILE='inventory.yaml'
+ fi
+ sed -e 's/password: .*/password: "[redacted]"/' < $FILE || true
+ echo ::endgroup::
+
+ - name: Install agent
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]'
+
+ - name: Install module
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module'
+
+ - name: "Honeycomb: Record deployment times"
+ if: ${{ always() }}
+ run: |
+ echo ::group::honeycomb step
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Deploy test system'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-3 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ echo ::endgroup::
+
+ - name: Run acceptance tests
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:acceptance:parallel' -- bundle exec rake 'litmus:acceptance:parallel'
+
+ - name: "Honeycomb: Record acceptance testing times"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Run acceptance tests'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-4 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+
+ - name: Remove test environment
+ if: ${{ always() }}
+ continue-on-error: true
+ run: |
+ if [[ -f inventory.yaml || -f spec/fixtures/litmus_inventory.yaml ]]; then
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:tear_down' -- bundle exec rake 'litmus:tear_down'
+ echo ::group::=== REQUEST ===
+ cat request.json || true
+ echo
+ echo ::endgroup::
+ fi
+
+ - name: "Honeycomb: Record removal times"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Remove test environment'
+
+ slack-workflow-status:
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ name: Post Workflow Status To Slack
+ needs:
+ - Acceptance
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Slack Workflow Notification
+ uses: puppetlabs/Gamesight-slack-workflow-status@pdk-templates-v1
+ with:
+ # Required Input
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ slack_webhook_url: ${{ secrets.SLACK_WEBHOOK }}
+ # Optional Input
+ channel: '#team-cat-bots'
+ name: 'GABot'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/pr_test.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/pr_test.yml
new file mode 100644
index 000000000..fd310e656
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/pr_test.yml
@@ -0,0 +1,185 @@
+name: "PR Testing"
+
+on: [pull_request]
+
+
+env:
+
+ HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
+ HONEYCOMB_DATASET: litmus tests
+
+jobs:
+ setup_matrix:
+ name: "Setup Test Matrix"
+ runs-on: ubuntu-20.04
+ outputs:
+ matrix: ${{ steps.get-matrix.outputs.matrix }}
+
+ steps:
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+
+ - name: "Honeycomb: Start first step"
+ run: |
+ echo STEP_ID=setup-environment >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Checkout Source
+ uses: actions/checkout@v2
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+
+ - name: Activate Ruby 2.7
+ uses: ruby/setup-ruby@v1
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ with:
+ ruby-version: "2.7"
+ bundler-cache: true
+
+ - name: Print bundle environment
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+
+ - name: "Honeycomb: Record Setup Environment time"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Environment'
+ echo STEP_ID=Setup-Acceptance-Test-Matrix >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Run validation steps
+ run: |
+ bundle exec rake validate
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+
+ - name: Setup Acceptance Test Matrix
+ id: get-matrix
+ run: |
+ if [ '${{ github.repository_owner }}' == 'puppetlabs' ]; then
+ buildevents cmd $TRACE_ID $STEP_ID matrix_from_metadata -- bundle exec matrix_from_metadata_v2
+ else
+ echo "::set-output name=matrix::{}"
+ fi
+
+ - name: "Honeycomb: Record Setup Test Matrix time"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Test Matrix'
+ Acceptance:
+ name: "${{matrix.platforms.label}}, ${{matrix.collection}}"
+ needs:
+ - setup_matrix
+ if: ${{ needs.setup_matrix.outputs.matrix != '{}' }}
+
+ runs-on: ubuntu-20.04
+ strategy:
+ fail-fast: false
+ matrix: ${{fromJson(needs.setup_matrix.outputs.matrix)}}
+
+ env:
+ BUILDEVENT_FILE: '../buildevents.txt'
+
+ steps:
+ - run: |
+ echo 'platform=${{ matrix.platforms.image }}' >> $BUILDEVENT_FILE
+ echo 'collection=${{ matrix.collection }}' >> $BUILDEVENT_FILE
+ echo 'label=${{ matrix.platforms.label }}' >> $BUILDEVENT_FILE
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+ matrix-key: ${{ matrix.platforms.label }}-${{ matrix.collection }}
+
+ - name: "Honeycomb: start first step"
+ run: |
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-1 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Checkout Source
+ uses: actions/checkout@v2
+
+ - name: Activate Ruby 2.7
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "2.7"
+ bundler-cache: true
+
+ - name: Print bundle environment
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+
+ - name: "Honeycomb: Record Setup Environment time"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Environment'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-2 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Provision test environment
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:provision ${{ matrix.platforms.image }}' -- bundle exec rake 'litmus:provision[${{matrix.platforms.provider}},${{ matrix.platforms.image }}]'
+ echo ::group::=== REQUEST ===
+ cat request.json || true
+ echo
+ echo ::endgroup::
+ echo ::group::=== INVENTORY ===
+ if [ -f 'spec/fixtures/litmus_inventory.yaml' ];
+ then
+ FILE='spec/fixtures/litmus_inventory.yaml'
+ elif [ -f 'inventory.yaml' ];
+ then
+ FILE='inventory.yaml'
+ fi
+ sed -e 's/password: .*/password: "[redacted]"/' < $FILE || true
+ echo ::endgroup::
+
+ - name: Install agent
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_agent ${{ matrix.collection }}' -- bundle exec rake 'litmus:install_agent[${{ matrix.collection }}]'
+
+ - name: Install module
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:install_module' -- bundle exec rake 'litmus:install_module'
+
+ - name: "Honeycomb: Record deployment times"
+ if: ${{ always() }}
+ run: |
+ echo ::group::honeycomb step
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Deploy test system'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-3 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ echo ::endgroup::
+ - name: Run acceptance tests
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:acceptance:parallel' -- bundle exec rake 'litmus:acceptance:parallel'
+
+ - name: "Honeycomb: Record acceptance testing times"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Run acceptance tests'
+ echo STEP_ID=${{ matrix.platforms.image }}-${{ matrix.collection }}-4 >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Remove test environment
+ if: ${{ always() }}
+ continue-on-error: true
+ run: |
+ if [[ -f inventory.yaml || -f spec/fixtures/litmus_inventory.yaml ]]; then
+ buildevents cmd $TRACE_ID $STEP_ID 'rake litmus:tear_down' -- bundle exec rake 'litmus:tear_down'
+ echo ::group::=== REQUEST ===
+ cat request.json || true
+ echo
+ echo ::endgroup::
+ fi
+
+ - name: "Honeycomb: Record removal times"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Remove test environment'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/release.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/release.yml
new file mode 100644
index 000000000..1509f6e91
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/release.yml
@@ -0,0 +1,47 @@
+name: "Publish module"
+
+on:
+ workflow_dispatch:
+
+jobs:
+ create-github-release:
+ name: Deploy GitHub Release
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ ref: ${{ github.ref }}
+ clean: true
+ fetch-depth: 0
+ - name: Get Version
+ id: gv
+ run: |
+ echo "::set-output name=ver::$(jq --raw-output .version metadata.json)"
+ - name: Create Release
+ uses: actions/create-release@v1
+ id: create_release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: "v${{ steps.gv.outputs.ver }}"
+ draft: false
+ prerelease: false
+
+ deploy-forge:
+ name: Deploy to Forge
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ ref: ${{ github.ref }}
+ clean: true
+ - name: "PDK Build"
+ uses: docker://puppet/pdk:nightly
+ with:
+ args: 'build'
+ - name: "Push to Forge"
+ uses: docker://puppet/pdk:nightly
+ with:
+ args: 'release publish --forge-token ${{ secrets.FORGE_API_KEY }} --force'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/spec.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/spec.yml
new file mode 100644
index 000000000..6c1ae10d8
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/spec.yml
@@ -0,0 +1,126 @@
+name: "Spec Tests"
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+ workflow_dispatch:
+ pull_request:
+
+
+env:
+ HONEYCOMB_WRITEKEY: 7f3c63a70eecc61d635917de46bea4e6
+ HONEYCOMB_DATASET: litmus tests
+
+jobs:
+ setup_matrix:
+ name: "Setup Test Matrix"
+ runs-on: ubuntu-20.04
+ outputs:
+ spec_matrix: ${{ steps.get-matrix.outputs.spec_matrix }}
+
+ steps:
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+
+ - name: "Honeycomb: Start first step"
+ run: |
+ echo STEP_ID=setup-environment >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Checkout Source
+ uses: actions/checkout@v2
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+
+ - name: Activate Ruby 2.7
+ uses: ruby/setup-ruby@v1
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ with:
+ ruby-version: "2.7"
+ bundler-cache: true
+
+ - name: Print bundle environment
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+ - name: "Honeycomb: Record Setup Environment time"
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Environment'
+ echo STEP_ID=Setup-Acceptance-Test-Matrix >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+ - name: Run Static & Syntax Tests
+ if: ${{ github.repository_owner == 'puppetlabs' }}
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'static_syntax_checks' -- bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop
+
+ - name: Setup Spec Test Matrix
+ id: get-matrix
+ run: |
+ if [ '${{ github.repository_owner }}' == 'puppetlabs' ]; then
+ buildevents cmd $TRACE_ID $STEP_ID matrix_from_metadata -- bundle exec matrix_from_metadata_v2
+ else
+ echo "::set-output name=spec_matrix::{}"
+ fi
+ - name: "Honeycomb: Record Setup Test Matrix time"
+ if: ${{ always() }}
+ run: |
+ buildevents step $TRACE_ID $STEP_ID $STEP_START 'Setup Test Matrix'
+ Spec:
+ name: "Spec Tests (Puppet: ${{matrix.puppet_version}}, Ruby Ver: ${{matrix.ruby_version}})"
+ needs:
+ - setup_matrix
+ if: ${{ needs.setup_matrix.outputs.spec_matrix != '{}' }}
+
+ runs-on: ubuntu-20.04
+ strategy:
+ fail-fast: false
+ matrix: ${{fromJson(needs.setup_matrix.outputs.spec_matrix)}}
+
+ env:
+ BUILDEVENT_FILE: '../buildevents.txt'
+ PUPPET_GEM_VERSION: ${{ matrix.puppet_version }}
+ FACTER_GEM_VERSION: 'https://github.com/puppetlabs/facter#main'
+
+ steps:
+ - run: |
+ echo "SANITIZED_PUPPET_VERSION=$(echo '${{ matrix.puppet_version }}' | sed 's/~> //g')" >> $GITHUB_ENV
+
+ - run: |
+ echo 'puppet_version=${{ env.SANITIZED_PUPPET_VERSION }}' >> $BUILDEVENT_FILE
+ - name: "Honeycomb: Start first step"
+ run: |
+ echo "STEP_ID=${{ env.SANITIZED_PUPPET_VERSION }}-spec" >> $GITHUB_ENV
+ echo STEP_START=$(date +%s) >> $GITHUB_ENV
+
+ - name: "Honeycomb: Start recording"
+ uses: puppetlabs/kvrhdn-gha-buildevents@pdk-templates-v1
+ with:
+ apikey: ${{ env.HONEYCOMB_WRITEKEY }}
+ dataset: ${{ env.HONEYCOMB_DATASET }}
+ job-status: ${{ job.status }}
+ matrix-key: ${{ env.SANITIZED_PUPPET_VERSION }}
+ - name: Checkout Source
+ uses: actions/checkout@v2
+
+ - name: "Activate Ruby ${{ matrix.ruby_version }}"
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{matrix.ruby_version}}
+ bundler-cache: true
+
+ - name: Print bundle environment
+ run: |
+ echo ::group::bundler environment
+ buildevents cmd $TRACE_ID $STEP_ID 'bundle env' -- bundle env
+ echo ::endgroup::
+
+
+ - name: Run parallel_spec tests
+ run: |
+ buildevents cmd $TRACE_ID $STEP_ID 'rake parallel_spec Puppet ${{ matrix.puppet_version }}, Ruby ${{ matrix.ruby_version }}' -- bundle exec rake parallel_spec
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/stale.yml b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/stale.yml
new file mode 100644
index 000000000..26d7e5b1f
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.github/workflows/stale.yml
@@ -0,0 +1,36 @@
+name: Audit aging issues/PRs
+
+on:
+ schedule:
+ - cron: "30 1 * * *"
+
+jobs:
+ audit:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ days-before-issue-stale: 90
+ days-before-pr-stale: 60
+ days-before-pr-close: 7
+ stale-issue-message: |
+ Hello! 👋
+
+ This issue has been open for a while and has had no recent activity. We've labelled it with `attention-needed` so that we can get a clear view of which issues need our attention.
+
+ If you are waiting on a response from us we will try and address your comments on a future Community Day.
+
+ Alternatively, if it is no longer relevant to you please close the issue with a comment.
+ stale-issue-label: 'attention-needed'
+ stale-pr-message: |
+ Hello! 👋
+
+ This pull request has been open for a while and has had no recent activity. We've labelled it with `attention-needed` so that we can get a clear view of which PRs need our attention.
+
+ If you are waiting on a response from us we will try and address your comments on a future Community Day.
+
+ Alternatively, if it is no longer relevant to you please close the PR with a comment.
+
+ Please note that if a pull request receives no update for 7 after it has been labelled, it will be closed. We are always happy to re-open pull request if they have been closed in error.
+ stale-pr-label: 'attention-needed'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.gitignore b/modules/utilities/unix/system/accounts_newer/accounts/.gitignore
new file mode 100644
index 000000000..988dcbbe6
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.gitignore
@@ -0,0 +1,28 @@
+.git/
+.*.sw[op]
+.metadata
+.yardoc
+.yardwarns
+*.iml
+/.bundle/
+/.idea/
+/.vagrant/
+/coverage/
+/bin/
+/doc/
+/Gemfile.local
+/Gemfile.lock
+/junit/
+/log/
+/pkg/
+/spec/fixtures/manifests/
+/spec/fixtures/modules/
+/tmp/
+/vendor/
+/convert_report.txt
+/update_report.txt
+.DS_Store
+.project
+.envrc
+/inventory.yaml
+/spec/fixtures/litmus_inventory.yaml
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.Dockerfile b/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.Dockerfile
new file mode 100644
index 000000000..0814c5e61
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.Dockerfile
@@ -0,0 +1,18 @@
+FROM gitpod/workspace-full
+RUN sudo wget https://apt.puppet.com/puppet-tools-release-bionic.deb && \
+ wget https://apt.puppetlabs.com/puppet6-release-bionic.deb && \
+ sudo dpkg -i puppet6-release-bionic.deb && \
+ sudo dpkg -i puppet-tools-release-bionic.deb && \
+ sudo apt-get update && \
+ sudo apt-get install -y pdk zsh puppet-agent && \
+ sudo apt-get clean && \
+ sudo rm -rf /var/lib/apt/lists/*
+RUN sudo usermod -s $(which zsh) gitpod && \
+ sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \
+ echo "plugins=(git gitignore github gem pip bundler python ruby docker docker-compose)" >> /home/gitpod/.zshrc && \
+ echo 'PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/puppetlabs/bin:/opt/puppetlabs/puppet/bin"' >> /home/gitpod/.zshrc && \
+ sudo /opt/puppetlabs/puppet/bin/gem install puppet-debugger hub -N && \
+ mkdir -p /home/gitpod/.config/puppet && \
+ /opt/puppetlabs/puppet/bin/ruby -r yaml -e "puts ({'disabled' => true}).to_yaml" > /home/gitpod/.config/puppet/analytics.yml
+RUN rm -f puppet6-release-bionic.deb puppet-tools-release-bionic.deb
+ENTRYPOINT /usr/bin/zsh
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.yml b/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.yml
new file mode 100644
index 000000000..9d89d9faa
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.gitpod.yml
@@ -0,0 +1,9 @@
+image:
+ file: .gitpod.Dockerfile
+
+tasks:
+ - init: pdk bundle install
+
+vscode:
+ extensions:
+ - puppet.puppet-vscode@1.2.0:f5iEPbmOj6FoFTOV6q8LTg==
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.pdkignore b/modules/utilities/unix/system/accounts_newer/accounts/.pdkignore
new file mode 100644
index 000000000..c538bea8b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.pdkignore
@@ -0,0 +1,47 @@
+.git/
+.*.sw[op]
+.metadata
+.yardoc
+.yardwarns
+*.iml
+/.bundle/
+/.idea/
+/.vagrant/
+/coverage/
+/bin/
+/doc/
+/Gemfile.local
+/Gemfile.lock
+/junit/
+/log/
+/pkg/
+/spec/fixtures/manifests/
+/spec/fixtures/modules/
+/tmp/
+/vendor/
+/convert_report.txt
+/update_report.txt
+.DS_Store
+.project
+.envrc
+/inventory.yaml
+/spec/fixtures/litmus_inventory.yaml
+/appveyor.yml
+/.editorconfig
+/.fixtures.yml
+/Gemfile
+/.gitattributes
+/.gitignore
+/.gitlab-ci.yml
+/.pdkignore
+/.puppet-lint.rc
+/Rakefile
+/rakelib/
+/.rspec
+/.rubocop.yml
+/.travis.yml
+/.yardopts
+/spec/
+/.vscode/
+/.sync.yml
+/.devcontainer/
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.puppet-lint.rc b/modules/utilities/unix/system/accounts_newer/accounts/.puppet-lint.rc
new file mode 100644
index 000000000..cc96ece05
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.puppet-lint.rc
@@ -0,0 +1 @@
+--relative
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.rspec b/modules/utilities/unix/system/accounts_newer/accounts/.rspec
new file mode 100644
index 000000000..16f9cdb01
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.rspec
@@ -0,0 +1,2 @@
+--color
+--format documentation
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.rubocop.yml b/modules/utilities/unix/system/accounts_newer/accounts/.rubocop.yml
new file mode 100644
index 000000000..31e8248ff
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.rubocop.yml
@@ -0,0 +1,519 @@
+---
+require:
+- rubocop-performance
+- rubocop-rspec
+AllCops:
+ DisplayCopNames: true
+ TargetRubyVersion: '2.5'
+ Include:
+ - "**/*.rb"
+ Exclude:
+ - bin/*
+ - ".vendor/**/*"
+ - "**/Gemfile"
+ - "**/Rakefile"
+ - pkg/**/*
+ - spec/fixtures/**/*
+ - vendor/**/*
+ - "**/Puppetfile"
+ - "**/Vagrantfile"
+ - "**/Guardfile"
+Layout/LineLength:
+ Description: People have wide screens, use them.
+ Max: 200
+RSpec/BeforeAfterAll:
+ Description: Beware of using after(:all) as it may cause state to leak between tests.
+ A necessary evil in acceptance testing.
+ Exclude:
+ - spec/acceptance/**/*.rb
+RSpec/HookArgument:
+ Description: Prefer explicit :each argument, matching existing module's style
+ EnforcedStyle: each
+RSpec/DescribeSymbol:
+ Exclude:
+ - spec/unit/facter/**/*.rb
+Style/BlockDelimiters:
+ Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to
+ be consistent then.
+ EnforcedStyle: braces_for_chaining
+Style/ClassAndModuleChildren:
+ Description: Compact style reduces the required amount of indentation.
+ EnforcedStyle: compact
+Style/EmptyElse:
+ Description: Enforce against empty else clauses, but allow `nil` for clarity.
+ EnforcedStyle: empty
+Style/FormatString:
+ Description: Following the main puppet project's style, prefer the % format format.
+ EnforcedStyle: percent
+Style/FormatStringToken:
+ Description: Following the main puppet project's style, prefer the simpler template
+ tokens over annotated ones.
+ EnforcedStyle: template
+Style/Lambda:
+ Description: Prefer the keyword for easier discoverability.
+ EnforcedStyle: literal
+Style/RegexpLiteral:
+ Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168
+ EnforcedStyle: percent_r
+Style/TernaryParentheses:
+ Description: Checks for use of parentheses around ternary conditions. Enforce parentheses
+ on complex expressions for better readability, but seriously consider breaking
+ it up.
+ EnforcedStyle: require_parentheses_when_complex
+Style/TrailingCommaInArguments:
+ Description: Prefer always trailing comma on multiline argument lists. This makes
+ diffs, and re-ordering nicer.
+ EnforcedStyleForMultiline: comma
+Style/TrailingCommaInArrayLiteral:
+ Description: Prefer always trailing comma on multiline literals. This makes diffs,
+ and re-ordering nicer.
+ EnforcedStyleForMultiline: comma
+Style/SymbolArray:
+ Description: Using percent style obscures symbolic intent of array's contents.
+ EnforcedStyle: brackets
+RSpec/MessageSpies:
+ EnforcedStyle: receive
+Style/Documentation:
+ Exclude:
+ - lib/puppet/parser/functions/**/*
+ - 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/modules/utilities/unix/system/accounts_newer/accounts/.sync.yml b/modules/utilities/unix/system/accounts_newer/accounts/.sync.yml
new file mode 100644
index 000000000..ccb750265
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.sync.yml
@@ -0,0 +1,33 @@
+---
+.gitattributes:
+ include:
+ 'files/shell/*': 'eol=lf'
+".gitlab-ci.yml":
+ delete: true
+appveyor.yml:
+ delete: true
+
+Gemfile:
+ optional:
+ ":development":
+ - gem: github_changelog_generator
+spec/spec_helper.rb:
+ mock_with: ":rspec"
+ coverage_report: true
+.gitpod.Dockerfile:
+ unmanaged: false
+.gitpod.yml:
+ unmanaged: false
+.github/workflows/nightly.yml:
+ unmanaged: false
+.github/workflows/pr_test.yml:
+ unmanaged: false
+.github/workflows/auto_release.yml:
+ unmanaged: false
+.github/workflows/spec.yml:
+ checks: 'syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop'
+ unmanaged: false
+.github/workflows/release.yml:
+ unmanaged: false
+.travis.yml:
+ delete: true
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.vscode/extensions.json b/modules/utilities/unix/system/accounts_newer/accounts/.vscode/extensions.json
new file mode 100644
index 000000000..2f1e4f73a
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.vscode/extensions.json
@@ -0,0 +1,6 @@
+{
+ "recommendations": [
+ "puppet.puppet-vscode",
+ "rebornix.Ruby"
+ ]
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/.yardopts b/modules/utilities/unix/system/accounts_newer/accounts/.yardopts
new file mode 100644
index 000000000..29c933bcf
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/.yardopts
@@ -0,0 +1 @@
+--markup markdown
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/CHANGELOG.md b/modules/utilities/unix/system/accounts_newer/accounts/CHANGELOG.md
new file mode 100644
index 000000000..e5261d252
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/CHANGELOG.md
@@ -0,0 +1,339 @@
+# Change log
+
+All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org).
+
+## [v7.2.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.2.0) - 2022-05-16
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v7.1.1...v7.2.0)
+
+### Added
+
+- Added new SSH key type. [#410](https://github.com/puppetlabs/puppetlabs-accounts/pull/410) ([PorkCharsui79](https://github.com/PorkCharsui79))
+
+- pdksync - (IAC-1753) - Add Support for AlmaLinux 8 [#397](https://github.com/puppetlabs/puppetlabs-accounts/pull/397) ([david22swan](https://github.com/david22swan))
+
+- pdksync - (IAC-1751) - Add Support for Rocky 8 [#395](https://github.com/puppetlabs/puppetlabs-accounts/pull/395) ([david22swan](https://github.com/david22swan))
+
+### Fixed
+
+- pdksync - (GH-iac-334) Remove Support for Ubuntu 16.04 [#401](https://github.com/puppetlabs/puppetlabs-accounts/pull/401) ([david22swan](https://github.com/david22swan))
+
+- pdksync - (IAC-1787) Remove Support for CentOS 6 [#398](https://github.com/puppetlabs/puppetlabs-accounts/pull/398) ([david22swan](https://github.com/david22swan))
+
+- pdksync - (IAC-1598) - Remove Support for Debian 8 [#394](https://github.com/puppetlabs/puppetlabs-accounts/pull/394) ([david22swan](https://github.com/david22swan))
+
+
+## [v7.1.1](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.1.1) (2021-08-25)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v7.1.0...v7.1.1)
+
+### Fixed
+
+- \(IAC-1741\) Allow stdlib v8.0.0 [\#392](https://github.com/puppetlabs/puppetlabs-accounts/pull/392) ([david22swan](https://github.com/david22swan))
+
+## [v7.1.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.1.0) (2021-08-16)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v7.0.2...v7.1.0)
+
+### Added
+
+- pdksync - \(IAC-1709\) - Add Support for Debian 11 [\#391](https://github.com/puppetlabs/puppetlabs-accounts/pull/391) ([david22swan](https://github.com/david22swan))
+- MODULES-11100 - Add sk-ecdsa public key support, and implement tests for sk-ecdsa and ecdsa keys [\#388](https://github.com/puppetlabs/puppetlabs-accounts/pull/388) ([vollmerk](https://github.com/vollmerk))
+
+## [v7.0.2](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.0.2) (2021-03-29)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v7.0.1...v7.0.2)
+
+### Fixed
+
+- \(IAC-1497\) - Removal of unsupported `translate` dependency [\#373](https://github.com/puppetlabs/puppetlabs-accounts/pull/373) ([david22swan](https://github.com/david22swan))
+- \(MODULES-10892\) Update name.pp [\#353](https://github.com/puppetlabs/puppetlabs-accounts/pull/353) ([LooOOooM](https://github.com/LooOOooM))
+
+## [v7.0.1](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.0.1) (2021-03-15)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v7.0.0...v7.0.1)
+
+### Fixed
+
+- \(MODULES-10960\) Selector needs multiple checks in brackets. [\#369](https://github.com/puppetlabs/puppetlabs-accounts/pull/369) ([tuxmea](https://github.com/tuxmea))
+
+## [v7.0.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v7.0.0) (2021-03-01)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.4.0...v7.0.0)
+
+### Changed
+
+- Update metadata.json - remove ubuntu 14.04 [\#368](https://github.com/puppetlabs/puppetlabs-accounts/pull/368) ([daianamezdrea](https://github.com/daianamezdrea))
+- pdksync - Remove Puppet 5 from testing and bump minimal version to 6.0.0 [\#359](https://github.com/puppetlabs/puppetlabs-accounts/pull/359) ([carabasdaniel](https://github.com/carabasdaniel))
+
+### Fixed
+
+- \(MODULES-10867\) Ensure ssh key name is unique based on type, content and description [\#340](https://github.com/puppetlabs/puppetlabs-accounts/pull/340) ([mdklapwijk](https://github.com/mdklapwijk))
+
+## [v6.4.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.4.0) (2020-12-14)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.3.0...v6.4.0)
+
+### Added
+
+- pdksync - \(maint\) - Add support for Puppet 7 [\#350](https://github.com/puppetlabs/puppetlabs-accounts/pull/350) ([pmcmaw](https://github.com/pmcmaw))
+- MODULES-10862 add support for authorized\_keys file mode [\#338](https://github.com/puppetlabs/puppetlabs-accounts/pull/338) ([simondeziel](https://github.com/simondeziel))
+
+## [v6.3.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.3.0) (2020-09-22)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.2.0...v6.3.0)
+
+### Added
+
+- Allow for Sensitive type passwords in accounts::user [\#333](https://github.com/puppetlabs/puppetlabs-accounts/pull/333) ([jarretlavallee](https://github.com/jarretlavallee))
+
+### Fixed
+
+- \(MODULES-10798\) Ensure group is created for user only if undefined [\#334](https://github.com/puppetlabs/puppetlabs-accounts/pull/334) ([michaeltlombardi](https://github.com/michaeltlombardi))
+
+## [v6.2.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.2.0) (2020-08-20)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.1.1...v6.2.0)
+
+### Added
+
+- pdksync - \(IAC-973\) - Update travis/appveyor to run on new default branch main [\#318](https://github.com/puppetlabs/puppetlabs-accounts/pull/318) ([david22swan](https://github.com/david22swan))
+- \(IAC-746\) - Add ubuntu 20.04 support [\#312](https://github.com/puppetlabs/puppetlabs-accounts/pull/312) ([david22swan](https://github.com/david22swan))
+
+### Fixed
+
+- \(IAC-975\) - Removal of inappropriate terminology in module [\#320](https://github.com/puppetlabs/puppetlabs-accounts/pull/320) ([pmcmaw](https://github.com/pmcmaw))
+
+## [v6.1.1](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.1.1) (2020-04-30)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.1.0...v6.1.1)
+
+### Fixed
+
+- MODULES-10550 fix keyspec parsing to allow whitespaces in options and… [\#291](https://github.com/puppetlabs/puppetlabs-accounts/pull/291) ([janit42](https://github.com/janit42))
+
+## [v6.1.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.1.0) (2020-02-03)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v6.0.0...v6.1.0)
+
+### Added
+
+- Employ more lenient username checks \(allow capitals\) [\#286](https://github.com/puppetlabs/puppetlabs-accounts/pull/286) ([mvandegarde](https://github.com/mvandegarde))
+- \(MODULES-10242\) Re-add Ubuntu 14 to supported OS list [\#281](https://github.com/puppetlabs/puppetlabs-accounts/pull/281) ([sheenaajay](https://github.com/sheenaajay))
+
+## [v6.0.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v6.0.0) (2019-11-11)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v5.0.0...v6.0.0)
+
+### Changed
+
+- pdksync - FM-8499 - remove ubuntu14 support [\#277](https://github.com/puppetlabs/puppetlabs-accounts/pull/277) ([lionce](https://github.com/lionce))
+
+### Added
+
+- \(FM-8671\) - Support added for CentOS 8 [\#278](https://github.com/puppetlabs/puppetlabs-accounts/pull/278) ([david22swan](https://github.com/david22swan))
+
+### Fixed
+
+- fix small typo on the root\_home key at Debian.yaml [\#260](https://github.com/puppetlabs/puppetlabs-accounts/pull/260) ([wandenberg](https://github.com/wandenberg))
+- Use user group instead of user name for sshkey owner group [\#258](https://github.com/puppetlabs/puppetlabs-accounts/pull/258) ([florindragos](https://github.com/florindragos))
+
+## [v5.0.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v5.0.0) (2019-09-10)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v4.2.0...v5.0.0)
+
+### Changed
+
+- \(MODULES-9712\) Move data into hiera. [\#241](https://github.com/puppetlabs/puppetlabs-accounts/pull/241) ([pillarsdotnet](https://github.com/pillarsdotnet))
+
+### Added
+
+- \(FM-8392\) Add debian 10 to provision.yaml [\#251](https://github.com/puppetlabs/puppetlabs-accounts/pull/251) ([ThoughtCrhyme](https://github.com/ThoughtCrhyme))
+
+### Fixed
+
+- \(MODULES-9849\) wrong order when removing user with custom sshkey file [\#250](https://github.com/puppetlabs/puppetlabs-accounts/pull/250) ([tuxmea](https://github.com/tuxmea))
+- fix problematic parsing of keyspec [\#246](https://github.com/puppetlabs/puppetlabs-accounts/pull/246) ([EECOLOR](https://github.com/EECOLOR))
+- \(MODULES-9697\) fix for correct management of sshkey\_custom\_path [\#242](https://github.com/puppetlabs/puppetlabs-accounts/pull/242) ([tuxmea](https://github.com/tuxmea))
+
+## [v4.2.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v4.2.0) (2019-08-02)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v4.1.0...v4.2.0)
+
+### Added
+
+- \(FM-8231\) Convert testing to litmus [\#230](https://github.com/puppetlabs/puppetlabs-accounts/pull/230) ([eimlav](https://github.com/eimlav))
+
+### Fixed
+
+- MODULES-9447 -- Narrow dependency between removed user and group. [\#232](https://github.com/puppetlabs/puppetlabs-accounts/pull/232) ([pillarsdotnet](https://github.com/pillarsdotnet))
+
+## [v4.1.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v4.1.0) (2019-05-29)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/v4.0.0...v4.1.0)
+
+### Added
+
+- \(FM-8023\) Add RedHat 8 support [\#227](https://github.com/puppetlabs/puppetlabs-accounts/pull/227) ([eimlav](https://github.com/eimlav))
+- \(MODULES-7469\) Add password\_max\_age parameter [\#221](https://github.com/puppetlabs/puppetlabs-accounts/pull/221) ([eimlav](https://github.com/eimlav))
+
+### Fixed
+
+- \(MODULES-8968\) Test account removal. [\#226](https://github.com/puppetlabs/puppetlabs-accounts/pull/226) ([pillarsdotnet](https://github.com/pillarsdotnet))
+
+## [v4.0.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/v4.0.0) (2019-05-10)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/3.2.0...v4.0.0)
+
+### Changed
+
+- pdksync - \(MODULES-8444\) - Raise lower Puppet bound [\#218](https://github.com/puppetlabs/puppetlabs-accounts/pull/218) ([david22swan](https://github.com/david22swan))
+- \(MODULES-8909\) Add type-aliases and auto-loading. [\#214](https://github.com/puppetlabs/puppetlabs-accounts/pull/214) ([pillarsdotnet](https://github.com/pillarsdotnet))
+
+### Fixed
+
+- \(MODULES-8909\) Allow periods in usernames. [\#220](https://github.com/puppetlabs/puppetlabs-accounts/pull/220) ([pillarsdotnet](https://github.com/pillarsdotnet))
+- Remove user when custom sshkey file is set [\#213](https://github.com/puppetlabs/puppetlabs-accounts/pull/213) ([tuxmea](https://github.com/tuxmea))
+
+## [3.2.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/3.2.0) (2019-01-18)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/3.1.0...3.2.0)
+
+### Added
+
+- \(MODULES-8302\) - Add allowdupe parameter [\#199](https://github.com/puppetlabs/puppetlabs-accounts/pull/199) ([eimlav](https://github.com/eimlav))
+- \(MODULES-8149\) - Addition of support for SLES 15 [\#197](https://github.com/puppetlabs/puppetlabs-accounts/pull/197) ([david22swan](https://github.com/david22swan))
+
+### Fixed
+
+- \(MODULES-8216\) - Fix fail when custom\_sshkey\_path and managehome=false [\#194](https://github.com/puppetlabs/puppetlabs-accounts/pull/194) ([eimlav](https://github.com/eimlav))
+- Fixing the limitations section of the README [\#191](https://github.com/puppetlabs/puppetlabs-accounts/pull/191) ([HelenCampbell](https://github.com/HelenCampbell))
+
+## [3.1.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/3.1.0) (2018-09-27)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/3.0.0...3.1.0)
+
+### Added
+
+- pdksync - \(FM-7392\) puppet 6 testing changes [\#187](https://github.com/puppetlabs/puppetlabs-accounts/pull/187) ([tphoney](https://github.com/tphoney))
+- pdksync - \(MODULES-6805\) metadata.json shows support for puppet 6 [\#185](https://github.com/puppetlabs/puppetlabs-accounts/pull/185) ([tphoney](https://github.com/tphoney))
+- \(LOC-173\) Delivering translation for readmes/README\_ja\_JP.markdown [\#177](https://github.com/puppetlabs/puppetlabs-accounts/pull/177) ([ehom](https://github.com/ehom))
+
+### Fixed
+
+- \(maint\) corrected filename extension for both en and ja [\#182](https://github.com/puppetlabs/puppetlabs-accounts/pull/182) ([ehom](https://github.com/ehom))
+- Only take care of ssh-keys if ensure is set to 'present' [\#174](https://github.com/puppetlabs/puppetlabs-accounts/pull/174) ([opteamax](https://github.com/opteamax))
+- Rename README.markdown to README.MD [\#173](https://github.com/puppetlabs/puppetlabs-accounts/pull/173) ([clairecadman](https://github.com/clairecadman))
+
+## [3.0.0](https://github.com/puppetlabs/puppetlabs-accounts/tree/3.0.0) (2018-09-07)
+
+[Full Changelog](https://github.com/puppetlabs/puppetlabs-accounts/compare/2.0.0...3.0.0)
+
+### Changed
+
+- Adding ability to specify custom ssh\_key location [\#149](https://github.com/puppetlabs/puppetlabs-accounts/pull/149) ([ggeldenhuis](https://github.com/ggeldenhuis))
+
+### Added
+
+- \(MODULES-7687\) - Added Darwin compatibility [\#167](https://github.com/puppetlabs/puppetlabs-accounts/pull/167) ([eimlav](https://github.com/eimlav))
+- \(FM-7287\) - i18n Process Implemented. [\#159](https://github.com/puppetlabs/puppetlabs-accounts/pull/159) ([david22swan](https://github.com/david22swan))
+- \(MODULES-5222\) - managevim option added to manifests. [\#156](https://github.com/puppetlabs/puppetlabs-accounts/pull/156) ([david22swan](https://github.com/david22swan))
+- \(FM-7289\) - Added Puppet 4 data types to parameters [\#155](https://github.com/puppetlabs/puppetlabs-accounts/pull/155) ([eimlav](https://github.com/eimlav))
+- \(MODULES-7671\) - Support spaces in ssh key options [\#153](https://github.com/puppetlabs/puppetlabs-accounts/pull/153) ([dleske](https://github.com/dleske))
+- \(FM-7254\) - Addition of support for Ubuntu 18.04 [\#150](https://github.com/puppetlabs/puppetlabs-accounts/pull/150) ([david22swan](https://github.com/david22swan))
+
+### Fixed
+
+- pdksync - \(MODULES-7658\) use beaker4 in puppet-module-gems [\#170](https://github.com/puppetlabs/puppetlabs-accounts/pull/170) ([tphoney](https://github.com/tphoney))
+- Fix error when deploying key into directory not owned by user [\#152](https://github.com/puppetlabs/puppetlabs-accounts/pull/152) ([tuxmea](https://github.com/tuxmea))
+
+## 2.0.0
+### Summary
+This release drops support for Debian 7, adds support for Debian 9 and includes several small features and bug fixes.
+
+#### Added
+- [FM-7052] Addition of Debian 9 support to accounts
+- (MODULES-3989) Allow management of local accounts despite an NSS
+- Allow mode for homedir to be undef
+- Add expiry property to user resource.
+
+#### Fixed
+- (MODULES-6607) - Update docs to reflect correct default value for ignore_password_if_empty.
+- Update tests and README
+- Removed Debian 7 support
+
+#### Bugfixes
+- Allow sshkeys to be reused for multiple accounts
+- Set `home_mode` explicitly in tests
+- Fix test for ssh key to allow new comment format
+
+
+## Supported Release [1.3.0]
+### Summary
+This release uses the PDK convert functionality which in return makes the module PDK compliant. It also includes a roll up of maintenance changes.
+
+#### Added
+- PDK Convert accounts ([MODULES-6328](https://tickets.puppet.com/browse/MODULES-6328)).
+
+#### Fixed
+- Don't create accounts::home_dir resources.
+- Multiple maintenance changes.
+
+## Supported Release [1.2.1]
+### Summary
+This release is to update the formatting of the module, Rubocop having been run for all ruby files and been set to run automatically on all future commits.
+
+### Changed
+- Rubocop has been implemented.
+
+## Supported Release 1.2.0
+### Summary
+This release is a rollup of changes. Several attributes have been added as requested and submitted from our community.
+
+#### Added
+- Attribute ignore_password\_if\_empty is added which, if set to true, shall ignore password changes if the password is empty.
+- Removal of dependency on group resource if create\_group is set to false.
+- Add attribute to allow custom group names.
+- Add attribute to set system user or group.
+- Add attribute to set the user or group to be the system account.
+- Add attribute to create a group (or not) with the username.
+- Add support for .forward.
+- Add support for ssh options in authorization_keys.
+- Add ECDSA support.
+- Add support for ssh authorized key options.
+- Allow the use of the \`source\` param for bash files
+- Removal of end-of-life Ubuntu 12.04 support from metadata.
+- Update Puppet version compatibility.
+- Modulesync and Gemfile updates.
+
+#### Fixed
+- Multiple fixes to tests.
+
+## Supported Release 1.1.0
+### Summary
+A feature rich release, with the addition of Debian 8 support. Also several generic fixes to tests.
+
+#### Features
+- Now allows SSH keys to be purged from user.
+- Multiple updates and fixes to the README.
+- RSpec-puppet has now been unpinned.
+- Addition of Debian 8 compatibility to metadata.
+- Addition of OSfamily fact to tests.
+- Several modulesync updates.
+
+#### Bugfixes
+- Multiple fixes to tests.
+
+## Supported Release 1.0.0
+### Summary:
+This is the initial release of the rewrite of puppetlabs-pe\_accounts for a more general usage.
+
+Differences from the pe\_accounts module is that the data model is gone, and thus the base class that accepts hashes (ie, from hiera). Instead, the module is designed around the use of the `accounts::user` defined resource.
+
+To regain the old hiera behavior, use the `create_resources()` function in combination with `accounts::user`; eg: `create_resources('accounts::user', hiera_hash('accounts::users'))`
+
+[1.3.0]:https://github.com/puppetlabs/puppetlabs-accounts/compare/1.2.1...1.3.0
+[1.2.1]:https://github.com/puppetlabs/puppetlabs-accounts/compare/1.2.0...1.2.1
+
+
+\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/CODEOWNERS b/modules/utilities/unix/system/accounts_newer/accounts/CODEOWNERS
new file mode 100644
index 000000000..a5d109e99
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/CODEOWNERS
@@ -0,0 +1,2 @@
+# Setting ownership to the modules team
+* @puppetlabs/modules
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/CONTRIBUTING.md b/modules/utilities/unix/system/accounts_newer/accounts/CONTRIBUTING.md
new file mode 100644
index 000000000..e7a3a7c3f
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/CONTRIBUTING.md
@@ -0,0 +1,3 @@
+# Contributing to Puppet modules
+
+Check out our [Contributing to Supported Modules Blog Post](https://puppetlabs.github.io/iac/docs/contributing_to_a_module.html) to find all the information that you will need.
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/Gemfile b/modules/utilities/unix/system/accounts_newer/accounts/Gemfile
new file mode 100644
index 000000000..a14223db6
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/Gemfile
@@ -0,0 +1,64 @@
+source ENV['GEM_SOURCE'] || 'https://rubygems.org'
+
+def location_for(place_or_version, fake_version = nil)
+ git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?}
+ file_url_regex = %r{\Afile:\/\/(?.*)}
+
+ if place_or_version && (git_url = place_or_version.match(git_url_regex))
+ [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact
+ elsif place_or_version && (file_url = place_or_version.match(file_url_regex))
+ ['>= 0', { path: File.expand_path(file_url[:path]), require: false }]
+ else
+ [place_or_version, { require: false }]
+ 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, platforms: [:ruby]
+ gem "github_changelog_generator", 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]
+end
+
+puppet_version = ENV['PUPPET_GEM_VERSION']
+facter_version = ENV['FACTER_GEM_VERSION']
+hiera_version = ENV['HIERA_GEM_VERSION']
+
+gems = {}
+
+gems['puppet'] = location_for(puppet_version)
+
+# If facter or hiera versions have been specified via the environment
+# variables
+
+gems['facter'] = location_for(facter_version) if facter_version
+gems['hiera'] = location_for(hiera_version) if hiera_version
+
+gems.each do |gem_name, gem_params|
+ gem gem_name, *gem_params
+end
+
+# Evaluate Gemfile.local and ~/.gemfile if they exist
+extra_gemfiles = [
+ "#{__FILE__}.local",
+ File.join(Dir.home, '.gemfile'),
+]
+
+extra_gemfiles.each do |gemfile|
+ if File.file?(gemfile) && File.readable?(gemfile)
+ eval(File.read(gemfile), binding)
+ end
+end
+# vim: syntax=ruby
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/HISTORY.md b/modules/utilities/unix/system/accounts_newer/accounts/HISTORY.md
new file mode 100755
index 000000000..4bd681e77
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/HISTORY.md
@@ -0,0 +1,87 @@
+## 2.0.0
+### Summary
+This release drops support for Debian 7, adds support for Debian 9 and includes several small features and bug fixes.
+
+#### Added
+- [FM-7052] Addition of Debian 9 support to accounts
+- (MODULES-3989) Allow management of local accounts despite an NSS
+- Allow mode for homedir to be undef
+- Add expiry property to user resource.
+
+#### Fixed
+- (MODULES-6607) - Update docs to reflect correct default value for ignore_password_if_empty.
+- Update tests and README
+- Removed Debian 7 support
+
+#### Bugfixes
+- Allow sshkeys to be reused for multiple accounts
+- Set `home_mode` explicitly in tests
+- Fix test for ssh key to allow new comment format
+
+
+## Supported Release [1.3.0]
+### Summary
+This release uses the PDK convert functionality which in return makes the module PDK compliant. It also includes a roll up of maintenance changes.
+
+#### Added
+- PDK Convert accounts ([MODULES-6328](https://tickets.puppet.com/browse/MODULES-6328)).
+
+#### Fixed
+- Don't create accounts::home_dir resources.
+- Multiple maintenance changes.
+
+## Supported Release [1.2.1]
+### Summary
+This release is to update the formatting of the module, Rubocop having been run for all ruby files and been set to run automatically on all future commits.
+
+### Changed
+- Rubocop has been implemented.
+
+## Supported Release 1.2.0
+### Summary
+This release is a rollup of changes. Several attributes have been added as requested and submitted from our community.
+
+#### Added
+- Attribute ignore_password\_if\_empty is added which, if set to true, shall ignore password changes if the password is empty.
+- Removal of dependency on group resource if create\_group is set to false.
+- Add attribute to allow custom group names.
+- Add attribute to set system user or group.
+- Add attribute to set the user or group to be the system account.
+- Add attribute to create a group (or not) with the username.
+- Add support for .forward.
+- Add support for ssh options in authorization_keys.
+- Add ECDSA support.
+- Add support for ssh authorized key options.
+- Allow the use of the \`source\` param for bash files
+- Removal of end-of-life Ubuntu 12.04 support from metadata.
+- Update Puppet version compatibility.
+- Modulesync and Gemfile updates.
+
+#### Fixed
+- Multiple fixes to tests.
+
+## Supported Release 1.1.0
+### Summary
+A feature rich release, with the addition of Debian 8 support. Also several generic fixes to tests.
+
+#### Features
+- Now allows SSH keys to be purged from user.
+- Multiple updates and fixes to the README.
+- RSpec-puppet has now been unpinned.
+- Addition of Debian 8 compatibility to metadata.
+- Addition of OSfamily fact to tests.
+- Several modulesync updates.
+
+#### Bugfixes
+- Multiple fixes to tests.
+
+## Supported Release 1.0.0
+### Summary:
+This is the initial release of the rewrite of puppetlabs-pe\_accounts for a more general usage.
+
+Differences from the pe\_accounts module is that the data model is gone, and thus the base class that accepts hashes (ie, from hiera). Instead, the module is designed around the use of the `accounts::user` defined resource.
+
+To regain the old hiera behavior, use the `create_resources()` function in combination with `accounts::user`; eg: `create_resources('accounts::user', hiera_hash('accounts::users'))`
+
+[1.3.0]:https://github.com/puppetlabs/puppetlabs-accounts/compare/1.2.1...1.3.0
+[1.2.1]:https://github.com/puppetlabs/puppetlabs-accounts/compare/1.2.0...1.2.1
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/LICENSE b/modules/utilities/unix/system/accounts_newer/accounts/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/NOTICE b/modules/utilities/unix/system/accounts_newer/accounts/NOTICE
new file mode 100644
index 000000000..149a4fc43
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/NOTICE
@@ -0,0 +1,15 @@
+Puppet Module - puppetlabs-accounts
+
+Copyright 2018 Puppet, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/README.md b/modules/utilities/unix/system/accounts_newer/accounts/README.md
new file mode 100644
index 000000000..65003d2ac
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/README.md
@@ -0,0 +1,255 @@
+# accounts
+
+#### Table of Contents
+1. [Description](#description)
+2. [Setup - The basics of getting started with accounts](#setup)
+3. [Usage - Configuration options and additional functionality](#usage)
+ * [Declare user accounts](#declare-user-accounts)
+ * [Customize the home directory](#customize-the-home-directory)
+ * [Lock accounts](#lock-accounts)
+ * [Manage SSH keys](#manage-ssh-keys)
+ * [Data in hiera](#data-in-hiera)
+4. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+ * [Data Types](#data-types)
+5. [Limitations - OS compatibility, etc.](#limitations)
+6. [Development - Guide for contributing to the module](#development)
+
+
+## Description
+
+The accounts module manages resources related to login and service accounts.
+
+This module works on many UNIX/Linux operating systems. It does not support configuring accounts on Microsoft Windows platforms.
+
+## Setup
+
+### Beginning with accounts
+
+Declare the `accounts` class in a Puppet-managed node's manifest:
+
+~~~puppet
+node default {
+ accounts::user { 'dan': }
+ accounts::user { 'morgan': }
+}
+~~~
+
+The above example creates accounts, home directories, and groups for Dan and Morgan.
+
+## Usage
+
+### Declare user accounts
+
+~~~puppet
+accounts::user { 'bob':
+ uid => '4001',
+ gid => '4001',
+ group => 'staff',
+ shell => '/bin/bash',
+ password => '!!',
+ locked => false,
+}
+~~~
+
+### Customize the home directory
+
+A simple bashrc and bash\_profile rc file is managed by Puppet for each account. These rc files add some simple aliases, update the prompt, add ~/bin to the path, and source the following files (which are not managed by this module) in the following order:
+
+ 1. `/etc/bashrc`
+ 2. `/etc/bashrc.puppet`
+ 3. `~/.bashrc.custom`
+
+Account holders can customize their shells by managing their bashrc.custom files. In addition, the system administrator can make profile changes that affect all accounts with a bash shell by managing the '/etc/bashrc.puppet' file.
+
+To install an email foward, configure the `.forward` file by using the `forward_content` or `forward_source` parameters.
+
+### Lock accounts
+
+Lock accounts by setting the `locked` parameter of an account to true.
+
+For example:
+
+~~~puppet
+accounts::user { 'villain':
+ comment => 'Bad Person',
+ locked => true
+}
+~~~
+
+The accounts module sets the account to an invalid shell appropriate for the system Puppet is managing and displays the following message if a user tries to access the account:
+
+~~~
+$ ssh villain@centos56
+This account is currently not available.
+Connection to 172.16.214.129 closed.
+~~~
+
+### Manage SSH keys
+
+Manage SSH keys with the `sshkeys` attribute of the `accounts::user` defined type. This parameter accepts an array of public key contents as strings.
+
+Example:
+
+~~~puppet
+accounts::user { 'jeff':
+ comment => 'Jeff McCune',
+ groups => [
+ 'admin',
+ 'sudonopw',
+ ],
+ uid => '1112',
+ gid => '1112',
+ sshkeys => [
+ 'ssh-rsa AAAAB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jeff@metamachine.net',
+ ],
+}
+~~~
+
+The module supports placing sshkeys in a custom location. If you specify a value
+for the `sshkey_custom_path` attribute of the `accounts::user` defined type, the
+module will place the keys in the specified file. The module will only manage
+the specified file and not the full path. If you set `purge_sshkeys` to true, and
+you have also set a custom path, it will only purge the ssh keys in the custom path.
+
+Example:
+
+~~~puppet
+accounts::user { 'gerrard':
+ sshkey_custom_path => '/var/lib/ssh/gerrard/authorized_keys',
+ sshkey_group => 'root',
+ sshkey_owner => 'root',
+ shell => '/bin/zsh',
+ comment => 'Gerrard Geldenhuis',
+ groups => [
+ 'engineering',
+ 'automation',
+ ],
+ uid => '1117',
+ gid => '1117',
+ sshkeys => [
+ 'ssh-rsa AAAAB9Aza...== gerrard@dirtyfruit.co.uk',
+ 'ssh-dss AAAAB9Aza...== gerrard@dojo.training',
+ ],
+ password => '!!',
+}
+~~~
+
+Setting `sshkey_custom_path` is typically associated with setting `AuthorizedKeysFile /var/lib/ssh/%u/authorized_keys` in your sshd config file.
+
+
+### Data in Hiera
+
+The accounts module supports storing all account data in Hiera.
+
+Example:
+
+~~~yaml
+accounts::group_defaults:
+ system: true
+accounts::group_list:
+ admins: {}
+ users: {}
+accounts::user_defaults:
+ groups: [ 'users' ]
+ managehome: true
+ system: false
+accounts::user_list:
+ admin:
+ groups: ['admins', 'users']
+ joe:
+ sshkeys:
+ - &joe_sshkey 'ssh-rsa ... joe@corp.com'
+ sally:
+ sshkeys:
+ - &sally_sshkey 'ssh-rsa ... sally@corp.com'
+ dba:
+ sshkeys:
+ - *joe_sshkey
+ - *sally_sshkey
+ system: true
+~~~
+
+~~~puppet
+include ::accounts
+~~~
+
+## Reference
+
+See [REFERENCE.md](https://github.com/puppetlabs/puppetlabs-accounts/blob/main/REFERENCE.md)
+
+
+### Data types
+
+#### `Accounts::Group::Hash`
+
+A hash of [`group`](https://puppet.com/docs/puppet/latesttypes/group.html#group) data suitable for passing as the second parameter to [`ensure_resources`](https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resources).
+
+#### `Accounts::Group::Provider`
+
+The allowed values for the [`provider`](https://puppet.com/docs/puppet/latest/types/group.html#group-attribute-provider) attribute. Currently, this is:
+* `aix`
+* `directoryservice`
+* `groupadd`
+* `ldap`
+* `pw`
+* `windows_adsi`
+
+#### `Accounts::Group::Resource`
+
+A struct of [`group` attributes](https://puppet.com/docs/puppet/latest/types/group.html#group-attributes) suitable for passing as the third parameter to [`ensure_resource`](https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resource).
+
+#### `Accounts::User::Expiry`
+
+Allows either `'absent'` or a `YYY-MM-DD` datestring.
+
+#### `Accounts::User::Hash`
+
+A hash of [`user`](https://puppet.com/docs/puppet/latest/types/user.html#user) data suitable for passing as the second parameter to [`ensure_resources`](https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resources).
+
+#### `Accounts::User::Iterations`
+
+The [`iterations`](https://puppet.com/docs/puppet/latest/types/user.html#user-attribute-iterations) attribute allows any positive integer, optionally expressed as a string.
+
+#### `Accounts::User::Name`
+
+Allows strings up to 32 characters long that begin with a lower case letter or underscore, followed by lower case letters, digits, underscores, or dashes, and optionally ending in a dollar sign. See [`useradd(8)`](http://manpages.ubuntu.com/manpages/precise/man8/useradd.8.html#caveats)
+
+#### `Accounts::User::PasswordMaxAge`
+
+Maximum number of days a password may be used before it must be changed. Allows any integer from `0` to `99999`. See [`user`](https://puppet.com/docs/puppet/latest/types/user.html#user-attribute-password_max_age) resource.
+
+#### `Accounts::User::Resource`
+
+A struct of [`user` attributes](https://puppet.com/docs/puppet/latest/types/user.html#user-attributes) suitable for passing as the third parameter to [`ensure_resource`](https://github.com/puppetlabs/puppetlabs-stdlib#ensure_resource).
+
+#### `Accounts::User::Uid`
+
+Allows any integer from `0` to `4294967295` (232 - 1), optionally expressed as a string.
+
+## Limitations
+
+For an extensive list of supported operating systems, see [metadata.json](https://github.com/puppetlabs/puppetlabs-accounts/blob/main/metadata.json)
+
+### Changes from pe\_accounts
+
+The accounts module is designed to take the place of the pe\_accounts module that shipped with PE versions 2015.2 and earlier. Some of the changes include the removal of the base class, improving the validation, and allowing more flexibility regarding which files should or should not be managed in a user's home directory.
+
+For example, the .bashrc and .bash\_profile files are not managed by default but allow custom content to be passed in using the `bashrc_content` and `bash_profile_content` parameters. The content for these two files as managed by pe\_accounts can continue to be used by passing `bashrc_content => file('accounts/shell/bashrc')` and `bash_profile_content => file('accounts/shell/bash_profile')` to the `accounts::user` defined type.
+
+## Development
+
+Acceptance tests for this module leverage [puppet_litmus](https://github.com/puppetlabs/puppet_litmus).
+To run the acceptance tests follow the instructions [here](https://github.com/puppetlabs/puppet_litmus/wiki/Tutorial:-use-Litmus-to-execute-acceptance-tests-with-a-sample-module-(MoTD)#install-the-necessary-gems-for-the-module).
+You can also find a tutorial and walkthrough of using Litmus and the PDK on [YouTube](https://www.youtube.com/watch?v=FYfR7ZEGHoE).
+
+If you run into an issue with this module, or if you would like to request a feature, please [file a ticket](https://tickets.puppetlabs.com/browse/MODULES/).
+Every Monday the Puppet IA Content Team has [office hours](https://puppet.com/community/office-hours) in the [Puppet Community Slack](http://slack.puppet.com/), alternating between an EMEA friendly time (1300 UTC) and an Americas friendly time (0900 Pacific, 1700 UTC).
+
+If you have problems getting this module up and running, please [contact Support](http://puppetlabs.com/services/customer-support).
+
+If you submit a change to this module, be sure to regenerate the reference documentation as follows:
+
+```bash
+puppet strings generate --format markdown --out REFERENCE.md
+```
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/REFERENCE.md b/modules/utilities/unix/system/accounts_newer/accounts/REFERENCE.md
new file mode 100644
index 000000000..52c57de96
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/REFERENCE.md
@@ -0,0 +1,800 @@
+# Reference
+
+
+
+## Table of Contents
+
+### Classes
+
+* [`accounts`](#accounts): This class auto-creates user and group resources from hiera data.
+* [`accounts::user::defaults`](#accountsuserdefaults): Load some user defaults from hiera data.
+
+### Defined types
+
+#### Public Defined types
+
+* [`accounts::user`](#accountsuser): This resource manages the user, group, vim/, .ssh/, .bash_profile, .bashrc,
+homedir, .ssh/authorized_keys files, and directories.
+
+#### Private Defined types
+
+* `accounts::home_dir`: This resource specifies how home directories are managed.
+* `accounts::key_management`: This resource specifies where ssh keys are managed.
+* `accounts::manage_keys`: This resource manages ssh keys for a user.
+
+### Functions
+
+* [`accounts_ssh_authorized_keys_line_parser`](#accounts_ssh_authorized_keys_line_parser): Parse an ssh authorized_keys line string into an array using its expected pattern by using a combination of regex matching and extracting the
+* [`accounts_ssh_options_parser`](#accounts_ssh_options_parser): Parse an ssh authorized_keys option string into an array using its expected pattern which matches a crazy regex slightly modified from shell
+
+### Data types
+
+* [`Accounts::Group::Hash`](#accountsgrouphash): A hash of group resources, keyed by group name.
+* [`Accounts::Group::Provider`](#accountsgroupprovider): The specific backend to use for this group resource.
+* [`Accounts::Group::Resource`](#accountsgroupresource): A hash of group attributes.
+* [`Accounts::User::Expiry`](#accountsuserexpiry): Account access will be denied after this date.
+* [`Accounts::User::Hash`](#accountsuserhash): A hash of user resources, keyed by user name.
+* [`Accounts::User::Iterations`](#accountsuseriterations): Chained computation iterations for the PBKDF2 password hash.
+* [`Accounts::User::Name`](#accountsusername): Each user or group should have a unique alphanumeric name.
+* [`Accounts::User::PasswordMaxAge`](#accountsuserpasswordmaxage): Maximum days between password changes.
+* [`Accounts::User::Resource`](#accountsuserresource): A hash of user attributes.
+* [`Accounts::User::Uid`](#accountsuseruid): Each user on a system should have a unique numeric uid.
+
+## Classes
+
+### `accounts`
+
+This class auto-creates user and group resources from hiera data.
+
+#### Parameters
+
+The following parameters are available in the `accounts` class:
+
+* [`group_defaults`](#group_defaults)
+* [`group_list`](#group_list)
+* [`user_defaults`](#user_defaults)
+* [`user_list`](#user_list)
+
+##### `group_defaults`
+
+Data type: `Accounts::Group::Resource`
+
+Hash of default attributes for group resources managed by this class.
+
+Default value: `{}`
+
+##### `group_list`
+
+Data type: `Accounts::Group::Hash`
+
+Hash of group resources for this class to manage. The hash is keyed by
+group name.
+
+Default value: `{}`
+
+##### `user_defaults`
+
+Data type: `Accounts::User::Resource`
+
+Hash of default attributes for accounts::user resources managed by this
+class.
+
+Default value: `{}`
+
+##### `user_list`
+
+Data type: `Accounts::User::Hash`
+
+Hash of accounts::user resources for this class to manage. The hash is
+keyed by user name.
+
+Default value: `{}`
+
+### `accounts::user::defaults`
+
+Load some user defaults from hiera data.
+
+#### Parameters
+
+The following parameters are available in the `accounts::user::defaults` class:
+
+* [`home_template`](#home_template)
+* [`locked_shell`](#locked_shell)
+* [`root_home`](#root_home)
+
+##### `home_template`
+
+Data type: `Stdlib::AbsolutePath`
+
+The sprintf template used to determine a user's home directory.
+
+Default value: `'/home/%s'`
+
+##### `locked_shell`
+
+Data type: `Stdlib::AbsolutePath`
+
+The shell assigned to locked user accounts.
+
+Default value: `'/sbin/nologin'`
+
+##### `root_home`
+
+Data type: `Stdlib::AbsolutePath`
+
+The home directory of the root user.
+
+Default value: `'/root'`
+
+## Defined types
+
+### `accounts::user`
+
+This resource manages the user, group, vim/, .ssh/, .bash_profile, .bashrc,
+homedir, .ssh/authorized_keys files, and directories.
+
+#### Examples
+
+##### Basic usage
+
+```puppet
+accounts::user { 'bob':
+ uid => '4001',
+ gid => '4001',
+ group => 'staff',
+ shell => '/bin/bash',
+ password => '!!',
+ locked => false,
+}
+```
+
+#### Parameters
+
+The following parameters are available in the `accounts::user` defined type:
+
+* [`ensure`](#ensure)
+* [`allowdupe`](#allowdupe)
+* [`bash_profile_content`](#bash_profile_content)
+* [`bash_profile_source`](#bash_profile_source)
+* [`bashrc_content`](#bashrc_content)
+* [`bashrc_source`](#bashrc_source)
+* [`comment`](#comment)
+* [`create_group`](#create_group)
+* [`expiry`](#expiry)
+* [`forcelocal`](#forcelocal)
+* [`forward_content`](#forward_content)
+* [`forward_source`](#forward_source)
+* [`gid`](#gid)
+* [`group`](#group)
+* [`groups`](#groups)
+* [`home`](#home)
+* [`home_mode`](#home_mode)
+* [`ignore_password_if_empty`](#ignore_password_if_empty)
+* [`iterations`](#iterations)
+* [`locked`](#locked)
+* [`managehome`](#managehome)
+* [`managevim`](#managevim)
+* [`membership`](#membership)
+* [`name`](#name)
+* [`password`](#password)
+* [`password_max_age`](#password_max_age)
+* [`purge_sshkeys`](#purge_sshkeys)
+* [`purge_user_home`](#purge_user_home)
+* [`salt`](#salt)
+* [`shell`](#shell)
+* [`sshkey_custom_path`](#sshkey_custom_path)
+* [`sshkey_group`](#sshkey_group)
+* [`sshkey_owner`](#sshkey_owner)
+* [`sshkey_mode`](#sshkey_mode)
+* [`sshkeys`](#sshkeys)
+* [`system`](#system)
+* [`uid`](#uid)
+
+##### `ensure`
+
+Data type: `Enum['absent','present']`
+
+Specifies whether the user, its primary group, homedir, and ssh keys should
+exist. Valid values are 'present' and 'absent'. Note that when a user is
+created, a group with the same name as the user is also created.
+
+Default value: `'present'`
+
+##### `allowdupe`
+
+Data type: `Boolean`
+
+Whether to allow duplicate UIDs. By default false
+
+Default value: ``false``
+
+##### `bash_profile_content`
+
+Data type: `Optional[String]`
+
+The content to place in the user's ~/.bash_profile file. Mutually exclusive
+to bash_profile_source.
+
+Default value: ``undef``
+
+##### `bash_profile_source`
+
+Data type: `Optional[Stdlib::Filesource]`
+
+A source file containing the content to place in the user's ~/.bash_profile
+file. Mutually exclusive to bash_profile_content.
+
+Default value: ``undef``
+
+##### `bashrc_content`
+
+Data type: `Optional[String]`
+
+The content to place in the user's ~/.bashrc file. Mutually exclusive to
+bashrc_source.
+
+Default value: ``undef``
+
+##### `bashrc_source`
+
+Data type: `Optional[Stdlib::Filesource]`
+
+A source file containing the content to place in the user's ~/.bashrc file.
+Mutually exclusive to bashrc_content.
+
+Default value: ``undef``
+
+##### `comment`
+
+Data type: `String`
+
+A comment describing or regarding the user.
+
+Default value: `$name`
+
+##### `create_group`
+
+Data type: `Boolean`
+
+Specifies if you want to create a group with the user's name.
+
+Default value: ``true``
+
+##### `expiry`
+
+Data type: `Optional[Accounts::User::Expiry]`
+
+Specifies the date the user account expires on. Valid values: YYYY-MM-DD
+date format, or 'absent' to remove expiry date.
+
+Default value: ``undef``
+
+##### `forcelocal`
+
+Data type: `Optional[Boolean]`
+
+Specifies whether you want to manage a local user/group that is also managed
+by a network name service.
+
+Default value: ``undef``
+
+##### `forward_content`
+
+Data type: `Optional[String]`
+
+The content to place in the user's ~/.forward file. Mutually exclusive to
+forward_source.
+
+Default value: ``undef``
+
+##### `forward_source`
+
+Data type: `Optional[Stdlib::Filesource]`
+
+A source file containing the content to place in the user's ~/.forward file.
+Mutually exclusive to forward_content.
+
+Default value: ``undef``
+
+##### `gid`
+
+Data type: `Optional[Accounts::User::Uid]`
+
+Specifies the gid of the user's primary group. Must be specified
+numerically.
+
+Default value: ``undef``
+
+##### `group`
+
+Data type: `Accounts::User::Name`
+
+Specifies the name of the user's primary group. By default, this uses a
+group named the same as user name
+
+Default value: `$name`
+
+##### `groups`
+
+Data type: `Array[Accounts::User::Name]`
+
+Specifies the user's group memberships.
+
+Default value: `[]`
+
+##### `home`
+
+Data type: `Optional[Stdlib::Unixpath]`
+
+Specifies the path to the user's home directory.
+
+- Linux, non-root user: '/home/$name'
+
+- Linux, root user: '/root'
+
+- Solaris, non-root user: '/export/home/$name'
+
+- Solaris, root user: '/'
+
+Default value: ``undef``
+
+##### `home_mode`
+
+Data type: `Optional[Stdlib::Filemode]`
+
+Manages the user's home directory permission mode. Valid values are in octal
+notation, specified as a string. Defaults to undef, which creates a home
+directory with 0700 permissions. It does not touch them if the directory
+already exists. Keeping it undef also allows a user to manage their own
+permissions. If home_mode is set, Puppet enforces the permissions on every
+run.
+
+Default value: ``undef``
+
+##### `ignore_password_if_empty`
+
+Data type: `Boolean`
+
+Specifies whether an empty password attribute should be ignored. If set to true,
+a password attribute that is defined but set to the empty string is ignored,
+allowing the password to be managed outside of this Puppet module. If set to false,
+it sets the password to an empty value.
+
+Default value: ``false``
+
+##### `iterations`
+
+Data type: `Optional[Accounts::User::Iterations]`
+
+This is the number of iterations of a chained computation of the PBKDF2
+password hash. This field is required for managing passwords on OS X >=
+10.8.
+
+Default value: ``undef``
+
+##### `locked`
+
+Data type: `Boolean`
+
+Specifies whether the account should be locked and the user prevented from
+logging in. Set to true for users whose login privileges have been revoked.
+
+Default value: ``false``
+
+##### `managehome`
+
+Data type: `Boolean`
+
+Specifies whether the user's home directory should be created when adding a
+user.
+
+Default value: ``true``
+
+##### `managevim`
+
+Data type: `Boolean`
+
+Specifies whether or not the .vim folder should be created within the
+managed accounts home directory.
+
+Default value: ``true``
+
+##### `membership`
+
+Data type: `Enum['inclusive','minimum']`
+
+Establishes whether specified groups should be considered the complete list
+(inclusive) or the minimum list (minimum) of groups to which the user
+belongs. Valid values: 'inclusive', 'minimum'.
+
+Default value: `'minimum'`
+
+##### `name`
+
+Name of the user.
+
+##### `password`
+
+Data type: `Variant[String, Sensitive[String]]`
+
+The user's password, in whatever encrypted format the local machine
+requires. Default: '!!', which prevents the user from logging in with a
+password.
+
+Default value: `'!!'`
+
+##### `password_max_age`
+
+Data type: `Optional[Accounts::User::PasswordMaxAge]`
+
+Maximum number of days a password may be used before it must be changed.
+Allows any integer from `0` to `99999`. See the
+[`user`](https://puppet.com/docs/puppet/latest/types/user.html#user-attribute-password_max_age)
+resource.
+
+Default value: ``undef``
+
+##### `purge_sshkeys`
+
+Data type: `Boolean`
+
+Whether keys not included in sshkeys should be removed from the user. If
+purge_sshkeys is true and sshkeys is an empty array, all SSH keys will be
+removed from the user.
+
+Default value: ``false``
+
+##### `purge_user_home`
+
+Data type: `Boolean`
+
+Whether to force recurse remove user home directories when removing a user.
+Defaults to false.
+
+Default value: ``false``
+
+##### `salt`
+
+Data type: `Optional[String]`
+
+This is the 32-byte salt used to generate the PBKDF2 password used in OS X.
+This field is required for managing passwords on OS X >= 10.8.
+
+Default value: ``undef``
+
+##### `shell`
+
+Data type: `Optional[Stdlib::Unixpath]`
+
+Manages the user shell.
+
+Default value: `'/bin/bash'`
+
+##### `sshkey_custom_path`
+
+Data type: `Optional[Stdlib::Unixpath]`
+
+Custom location for ssh public key file.
+
+Default value: ``undef``
+
+##### `sshkey_group`
+
+Data type: `Optional[Accounts::User::Name]`
+
+Specifies the group of the sshkey file
+
+Default value: `$group`
+
+##### `sshkey_owner`
+
+Data type: `Optional[Accounts::User::Name]`
+
+Specifies the owner of the sshkey file
+
+Default value: `$name`
+
+##### `sshkey_mode`
+
+Data type: `Variant[Integer[0],String]`
+
+Specifies the mode of the sshkey file .ssh/authorized_keys.
+
+Default value: `'0600'`
+
+##### `sshkeys`
+
+Data type: `Array[String]`
+
+An array of SSH public keys associated with the user. These should be
+complete public key strings that include the type, content and name of the
+key, exactly as it would appear in its id_*.pub file, or with an optional
+options string preceding the other components, as it would appear as an
+entry in an authorized_keys file. Must be an array.
+
+Examples:
+
+- ssh-rsa AAAAB3NzaC1y... bob@example.com
+
+- from="myhost.example.com,192.168.1.1" ssh-rsa AAAAQ4ng... bob2@example.com
+
+Note that for multiple keys, the name component (the last) must be unique.
+
+Default value: `[]`
+
+##### `system`
+
+Data type: `Boolean`
+
+Specifies if you want to create a system account.
+
+Default value: ``false``
+
+##### `uid`
+
+Data type: `Optional[Accounts::User::Uid]`
+
+Specifies the user's uid number. Must be specified numerically.
+
+Default value: ``undef``
+
+## Functions
+
+### `accounts_ssh_authorized_keys_line_parser`
+
+Type: Ruby 4.x API
+
+Parse an ssh authorized_keys line string into an array using its expected
+pattern by using a combination of regex matching and extracting the substring
+before the match as ssh-options. This allows whitespaces inside the options
+and inside the comment and is consistent with the behavior of openssh.
+The returned options element can by an empty string.
+
+#### Examples
+
+##### Calling the function
+
+```puppet
+accounts_ssh_authorized_keys_line_parser_string('options ssh-rsa AAAA... comment)
+```
+
+#### `accounts_ssh_authorized_keys_line_parser(String $str)`
+
+Parse an ssh authorized_keys line string into an array using its expected
+pattern by using a combination of regex matching and extracting the substring
+before the match as ssh-options. This allows whitespaces inside the options
+and inside the comment and is consistent with the behavior of openssh.
+The returned options element can by an empty string.
+
+Returns: `Array` of authroized_keys_line components:
+['options','keytype','key','comment']
+
+##### Examples
+
+###### Calling the function
+
+```puppet
+accounts_ssh_authorized_keys_line_parser_string('options ssh-rsa AAAA... comment)
+```
+
+##### `str`
+
+Data type: `String`
+
+ssh authorized_keys line string
+
+### `accounts_ssh_options_parser`
+
+Type: Ruby 4.x API
+
+Parse an ssh authorized_keys option string into an array using its expected pattern which matches a crazy regex slightly modified
+from shell words. The pattern should be a string.
+
+#### Examples
+
+##### Calling the function
+
+```puppet
+accounts_ssh_option_parser_string()
+```
+
+#### `accounts_ssh_options_parser(String $str)`
+
+Parse an ssh authorized_keys option string into an array using its expected pattern which matches a crazy regex slightly modified
+from shell words. The pattern should be a string.
+
+Returns: `Array` Separated components of the string
+
+##### Examples
+
+###### Calling the function
+
+```puppet
+accounts_ssh_option_parser_string()
+```
+
+##### `str`
+
+Data type: `String`
+
+ssh authorized_keys option string
+
+## Data types
+
+### `Accounts::Group::Hash`
+
+Group resoureces hash.
+Passed as the second parameter of the ensure_resources function.
+
+Alias of
+
+```puppet
+Hash[Accounts::User::Name, Accounts::Group::Resource]
+```
+
+### `Accounts::Group::Provider`
+
+Group provider.
+You will seldom need to specify this -- Puppet will usually discover the
+appropriate provider for your platform.
+
+Alias of
+
+```puppet
+Enum['aix', 'directoryservice', 'groupadd', 'ldap', 'pw', 'windows_adsi']
+```
+
+### `Accounts::Group::Resource`
+
+Group attributes hash.
+Passed as the third parameter of the ensure_resources function.
+
+Alias of
+
+```puppet
+Struct[{ Optional[ensure] => Enum['absent', 'present'],
+ Optional[allowdupe] => Boolean,
+ Optional[auth_membership] => Boolean,
+ Optional[forcelocal] => Boolean,
+ Optional[gid] => Accounts::User::Uid,
+ Optional[members] => Array[Accounts::User::Name],
+ Optional[name] => Accounts::User::Name,
+ Optional[provider] => Accounts::Group::Provider,
+ Optional[system] => Boolean,
+ }]
+```
+
+### `Accounts::User::Expiry`
+
+Account expiration date.
+Either 'absent' or a YYYY-MM-DD datestring.
+
+Alias of
+
+```puppet
+Variant[Enum['absent'], Pattern[/\A(19|[2-9]\d)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\z/]]
+```
+
+### `Accounts::User::Hash`
+
+User resources hash.
+Passed as the second parameter of the ensure_resources function.
+
+Alias of
+
+```puppet
+Hash[Accounts::User::Name, Accounts::User::Resource]
+```
+
+### `Accounts::User::Iterations`
+
+Password hash iterations.
+This parameter is used in OS X, and is required for managing passwords
+on OS X 10.8 and newer.
+
+Alias of
+
+```puppet
+Variant[Integer[1,], Pattern[/\A[1-9]\d*\z/]]
+```
+
+### `Accounts::User::Name`
+
+Account (user or group) name.
+From useradd(8): It is usually recommended to only use usernames
+that begin with a lower case letter or an underscore, followed by lower case
+letters, digits, underscores, or dashes. They can end with a dollar sign.
+Usernames may only be up to 32 characters long.
+
+Many installations also allow capitals or periods, for example to separate first and
+last names.
+
+Alias of
+
+```puppet
+Pattern[/\A[a-zA-Z0-9_]([a-zA-Z.0-9_-]{0,30}[a-zA-Z0-9_$-])?\z/]
+```
+
+### `Accounts::User::PasswordMaxAge`
+
+Max password age.
+On most systems, the default value of 99999 is about 274 years, which
+effectively disables password aging.
+
+Alias of
+
+```puppet
+Integer[1, 99999]
+```
+
+### `Accounts::User::Resource`
+
+User attributes hash.
+Passed as the third parameter of the ensure_resources function.
+
+Alias of
+
+```puppet
+Struct[{ Optional[ensure] => Enum['absent','present'],
+ Optional[allowdupe] => Boolean,
+ Optional[bash_profile_content] => String,
+ Optional[bash_profile_source] => Stdlib::Filesource,
+ Optional[bashrc_content] => String,
+ Optional[bashrc_source] => Stdlib::Filesource,
+ Optional[comment] => String,
+ Optional[create_group] => Boolean,
+ Optional[expiry] => Accounts::User::Expiry,
+ Optional[forcelocal] => Boolean,
+ Optional[forward_content] => String,
+ Optional[forward_source] => Stdlib::Filesource,
+ Optional[gid] => Accounts::User::Uid,
+ Optional[group] => Accounts::User::Name,
+ Optional[groups] => Array[Accounts::User::Name],
+ Optional[name] => Accounts::User::Name,
+ Optional[home] => Stdlib::Unixpath,
+ Optional[home_mode] => Stdlib::Filemode,
+ Optional[ignore_password_if_empty] => Boolean,
+ Optional[iterations] => Accounts::User::Iterations,
+ Optional[locked] => Boolean,
+ Optional[managehome] => Boolean,
+ Optional[managevim] => Boolean,
+ Optional[membership] => Enum['inclusive','minimum'],
+ Optional[name] => Accounts::User::Name,
+ Optional[password] => String,
+ Optional[password_max_age] => Accounts::User::PasswordMaxAge,
+ Optional[purge_sshkeys] => Boolean,
+ Optional[purge_user_home] => Boolean,
+ Optional[salt] => String,
+ Optional[shell] => Stdlib::Unixpath,
+ Optional[sshkey_custom_path] => Stdlib::Unixpath,
+ Optional[sshkey_owner] => Accounts::User::Name,
+ Optional[sshkey_group] => Accounts::User::Name,
+ Optional[sshkeys] => Array[String],
+ Optional[system] => Boolean,
+ Optional[uid] => Accounts::User::Uid,
+ }]
+```
+
+### `Accounts::User::Uid`
+
+Numeric user ID.
+On most Unix systems, the highest uid is 2^32 - 1, or 4294967295.
+
+Alias of
+
+```puppet
+Variant[Integer[0,4294967295], Pattern[/\A0\z/,
+ /\A[1-3]\d{0,9}\z/,
+ /\A[4-9]\d{0,8}\z/,
+ /\A4[0-1]\d{8}\z/,
+ /\A42[0-8]\d{7}\z/,
+ /\A429[0-3]\d{6}\z/,
+ /\A4294[0-8]\d{5}\z/,
+ /\A42949[0-5]\d{4}\z/,
+ /\A429496[0-6]\d{3}\z/,
+ /\A4294967[0-1]\d{2}\z/,
+ /\A42949672[0-8]\d\z/,
+ /\A429496729[0-5]\z/,
+ ]]
+```
+
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/Rakefile b/modules/utilities/unix/system/accounts_newer/accounts/Rakefile
new file mode 100644
index 000000000..0f8754eb6
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/Rakefile
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+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'
+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?
+
+def changelog_user
+ return unless Rake.application.top_level_tasks.include? "changelog"
+ returnVal = nil || JSON.load(File.read('metadata.json'))['author']
+ raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil?
+ puts "GitHubChangelogGenerator user:#{returnVal}"
+ returnVal
+end
+
+def changelog_project
+ return unless Rake.application.top_level_tasks.include? "changelog"
+
+ returnVal = nil
+ returnVal ||= begin
+ metadata_source = JSON.load(File.read('metadata.json'))['source']
+ metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z})
+
+ metadata_source_match && metadata_source_match[1]
+ end
+
+ raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil?
+
+ puts "GitHubChangelogGenerator project:#{returnVal}"
+ returnVal
+end
+
+def changelog_future_release
+ return unless Rake.application.top_level_tasks.include? "changelog"
+ returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version']
+ raise "unable to find the future_release (version) in metadata.json" if returnVal.nil?
+ puts "GitHubChangelogGenerator future_release:#{returnVal}"
+ returnVal
+end
+
+PuppetLint.configuration.send('disable_relative')
+
+
+if Bundler.rubygems.find_name('github_changelog_generator').any?
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
+ raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil?
+ config.user = "#{changelog_user}"
+ config.project = "#{changelog_project}"
+ config.future_release = "#{changelog_future_release}"
+ config.exclude_labels = ['maintenance']
+ config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)."
+ config.add_pr_wo_labels = true
+ config.issues = false
+ config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB"
+ config.configure_sections = {
+ "Changed" => {
+ "prefix" => "### Changed",
+ "labels" => ["backwards-incompatible"],
+ },
+ "Added" => {
+ "prefix" => "### Added",
+ "labels" => ["enhancement", "feature"],
+ },
+ "Fixed" => {
+ "prefix" => "### Fixed",
+ "labels" => ["bug", "documentation", "bugfix"],
+ },
+ }
+ end
+else
+ desc 'Generate a Changelog from GitHub'
+ task :changelog do
+ raise < 1.15'
+ condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')"
+EOM
+ end
+end
+
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/accounts.pp b/modules/utilities/unix/system/accounts_newer/accounts/accounts.pp
new file mode 100644
index 000000000..cf05ba4bd
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/accounts.pp
@@ -0,0 +1,14 @@
+# just install puppet module for other modules to use
+
+# example use:
+# accounts::user { 'user':
+# uid => '4001',
+# gid => '4001',
+# shell => '/bin/bash',
+# name => 'user',
+# # password = password
+# password => '$6$$bLTg4cpho8PIUrjfsE7qlU08Qx2UEfw..xOc6I1wpGVtyVYToGrr7BzRdAAnEr5lYFr1Z9WcCf1xNZ1HG9qFW1',
+#
+# # sshkeys => "ssh-rsa AAAA...",
+# # locked => false,
+# }
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/data/Debian.yaml b/modules/utilities/unix/system/accounts_newer/accounts/data/Debian.yaml
new file mode 100644
index 000000000..00697ccac
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/data/Debian.yaml
@@ -0,0 +1,5 @@
+---
+
+accounts::user::defaults::home_template: '/home/%s'
+accounts::user::defaults::locked_shell: '/usr/sbin/nologin'
+accounts::user::defaults::root_home: '/root'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/data/Solaris.yaml b/modules/utilities/unix/system/accounts_newer/accounts/data/Solaris.yaml
new file mode 100644
index 000000000..1ddea8dee
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/data/Solaris.yaml
@@ -0,0 +1,5 @@
+---
+
+accounts::user::defaults::home_template: '/export/home/%s'
+accounts::user::defaults::locked_shell: '/usr/bin/false'
+accounts::user::defaults::root_home: '/'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/data/common.yaml b/modules/utilities/unix/system/accounts_newer/accounts/data/common.yaml
new file mode 100644
index 000000000..2fbf0ffd7
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/data/common.yaml
@@ -0,0 +1 @@
+--- {}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location.pp b/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location.pp
new file mode 100644
index 000000000..fbf0b12cb
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location.pp
@@ -0,0 +1,46 @@
+group { 'admin':
+ gid => 3000,
+}
+group { 'sudo':
+ gid => 3001,
+}
+group { 'sudonopw':
+ gid => 3002,
+}
+group { 'developer':
+ gid => 3003,
+}
+group { 'ops':
+ gid => 3004,
+}
+
+file { '/var/lib/ssh/jeff':
+ ensure => directory,
+ owner => 'jeff',
+ group => 'jeff',
+}
+
+accounts::user { 'jeff':
+ sshkey_custom_path => '/var/lib/ssh/jeff/authorized_keys',
+ sshkey_group => 'root',
+ sshkey_owner => 'root',
+ shell => '/bin/zsh',
+ comment => 'Jeff McCune',
+ groups => [
+ 'admin',
+ 'sudonopw',
+ ],
+ uid => '1112',
+ gid => '1112',
+ locked => true,
+ sshkeys => [
+ 'ssh-rsa AAAAB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jeff@metamachine.net',
+ ],
+ password => '!!',
+}
+accounts::user { 'dan':
+ comment => 'Dan Bode',
+ uid => '1109',
+ gid => '1109',
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location_purge_keys.pp b/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location_purge_keys.pp
new file mode 100644
index 000000000..11332adbf
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/examples/custom_key_location_purge_keys.pp
@@ -0,0 +1,40 @@
+group { 'admin':
+ gid => 3000,
+}
+group { 'sudo':
+ gid => 3001,
+}
+group { 'sudonopw':
+ gid => 3002,
+}
+group { 'developer':
+ gid => 3003,
+}
+group { 'ops':
+ gid => 3004,
+}
+
+file { '/var/lib/ssh/jeff':
+ ensure => directory,
+ owner => 'jeff',
+ group => 'jeff',
+}
+
+accounts::user { 'jeff':
+ sshkey_custom_path => '/var/lib/ssh/jeff/authorized_keys',
+ shell => '/bin/zsh',
+ comment => 'Jeff McCune',
+ purge_sshkeys => true,
+ groups => [
+ 'admin',
+ 'sudonopw',
+ ],
+ uid => '1112',
+ gid => '1112',
+ locked => true,
+ sshkeys => [
+ 'ssh-rsa BBBBB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss BBBBB3Nza...== jeff@metamachine.net',
+ ],
+ password => '!!',
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/examples/group_common.pp b/modules/utilities/unix/system/accounts_newer/accounts/examples/group_common.pp
new file mode 100644
index 000000000..7fdc859f3
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/examples/group_common.pp
@@ -0,0 +1,23 @@
+# Use a variable OR with hiera_hash():
+# This example uses a common group name for both users
+
+$users_hash = {
+ 'jblow' => {
+ 'comment' => 'Joe Blow',
+ 'groups' => [wheel],
+ 'uid' => '1115',
+ 'gid' => '1115',
+ 'group' => 'mrblow',
+ 'sshkeys' => [
+ 'ssh-rsa AAAAB3Nza...== jblow@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jblow@googler.net',
+ ],
+ 'password' => '!!',
+ },
+ 'kblow' => {
+ 'comment' => 'Ken Blow',
+ 'group' => 'mrblow',
+ 'password' => '!!',
+ },
+}
+create_resources('accounts::user', $users_hash)
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group.pp b/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group.pp
new file mode 100644
index 000000000..f82b8d9ad
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group.pp
@@ -0,0 +1,37 @@
+group { 'admin':
+ gid => 3000,
+}
+group { 'sudo':
+ gid => 3001,
+}
+group { 'sudonopw':
+ gid => 3002,
+}
+group { 'developer':
+ gid => 3003,
+}
+group { 'ops':
+ gid => 3004,
+}
+
+accounts::user { 'jeff':
+ shell => '/bin/zsh',
+ comment => 'Jeff McCune',
+ groups => [
+ 'admin',
+ 'sudonopw',
+ ],
+ uid => '1112',
+ gid => '1112',
+ locked => true,
+ sshkeys => [
+ 'ssh-rsa AAAAB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jeff@metamachine.net',
+ ],
+ password => '!!',
+}
+accounts::user { 'dan':
+ comment => 'Dan Bode',
+ uid => '1109',
+ gid => '1109',
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group_hash.pp b/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group_hash.pp
new file mode 100644
index 000000000..c313656c1
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/examples/user_group_hash.pp
@@ -0,0 +1,31 @@
+# Use a variable OR with hiera_hash():
+$groups_hash = {
+ 'admin' => { gid => '3000' },
+ 'sudo' => { gid => '3001' },
+ 'sudonopw' => { gid => '3002' },
+ 'developer' => { gid => '3003' },
+ 'ops' => { gid => '3004' },
+}
+create_resources('group', $groups_hash)
+
+$users_hash = {
+ 'jeff' => {
+ 'shell' => '/bin/zsh',
+ 'comment' => 'Jeff McCune',
+ 'groups' => [admin, sudonopw,],
+ 'uid' => '1112',
+ 'gid' => '1112',
+ 'locked' => true,
+ 'sshkeys' => [
+ 'ssh-rsa AAAAB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jeff@metamachine.net',
+ ],
+ 'password' => '!!',
+ },
+ 'dan' => {
+ 'comment' => 'Dan Bode',
+ 'uid' => '1109',
+ 'gid' => '1109',
+ },
+}
+create_resources('accounts::user', $users_hash)
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bash_profile b/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bash_profile
new file mode 100644
index 000000000..026233f08
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bash_profile
@@ -0,0 +1,13 @@
+# .bash_profile
+
+# Get the aliases and functions
+if [ -f ~/.bashrc ]; then
+ . ~/.bashrc
+fi
+
+# User specific environment and startup programs
+
+PATH=$PATH:$HOME/bin
+
+export PATH
+unset USERNAME
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bashrc b/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bashrc
new file mode 100644
index 000000000..e866f7a1e
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/files/shell/bashrc
@@ -0,0 +1,27 @@
+# .bashrc
+# This file is managed by Puppet. Changes will be overwritten.
+# Please edit ~/.bashrc.custom instead of this file!
+
+# User specific aliases and functions
+
+alias rm='rm -i'
+alias cp='cp -i'
+alias mv='mv -i'
+
+# Set the prompt
+PS1='\u@\h:\w\$ '
+
+# Source global definitions
+if [ -f /etc/bashrc ]; then
+ . /etc/bashrc
+fi
+
+# Puppet specific definitions
+if [ -f /etc/bashrc.puppet ]; then
+ . /etc/bashrc.puppet
+fi
+
+# Account holder definitions
+if [ -f ~/.bashrc.custom ]; then
+ . ~/.bashrc.custom
+fi
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/hiera.yaml b/modules/utilities/unix/system/accounts_newer/accounts/hiera.yaml
new file mode 100644
index 000000000..0edd3fab8
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/hiera.yaml
@@ -0,0 +1,11 @@
+---
+
+version: 5
+
+defaults:
+ data_hash: 'yaml_data'
+ datadir: 'data'
+
+hierarchy:
+ - name: 'os.family'
+ path: '%{facts.os.family}.yaml'
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_authorized_keys_line_parser.rb b/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_authorized_keys_line_parser.rb
new file mode 100644
index 000000000..5a08e2b21
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_authorized_keys_line_parser.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+# Parse an ssh authorized_keys line string into an array using its expected
+# pattern by using a combination of regex matching and extracting the substring
+# before the match as ssh-options. This allows whitespaces inside the options
+# and inside the comment and is consistent with the behavior of openssh.
+# The returned options element can by an empty string.
+Puppet::Functions.create_function(:accounts_ssh_authorized_keys_line_parser) do
+ # @param str ssh authorized_keys line string
+ # @return [Array] of authroized_keys_line components:
+ # ['options','keytype','key','comment']
+ # @example Calling the function
+ # accounts_ssh_authorized_keys_line_parser_string('options ssh-rsa AAAA... comment)
+ dispatch :accounts_ssh_authorized_keys_line_parser_string do
+ param 'String', :str
+ end
+
+ def accounts_ssh_authorized_keys_line_parser_string(str)
+ matched = str.match(%r{((sk-ssh-ed25519|sk-ecdsa-|ssh-|ecdsa-)[^\s]+)\s+([^\s]+)\s+(.*)$})
+ raise ArgumentError, 'Wrong Keyline format!' unless matched && matched.length == 5
+ options = str[0, str.index(matched[0])].rstrip
+ [options, matched[1], matched[3], matched[4]]
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_options_parser.rb b/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_options_parser.rb
new file mode 100644
index 000000000..a76ca1b93
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/lib/puppet/functions/accounts_ssh_options_parser.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# Parse an ssh authorized_keys option string into an array using its expected pattern which matches a crazy regex slightly modified
+# from shell words. The pattern should be a string.
+Puppet::Functions.create_function(:accounts_ssh_options_parser) do
+ # @param str ssh authorized_keys option string
+ # @return [Array] Separated components of the string
+ # @example Calling the function
+ # accounts_ssh_option_parser_string()
+ dispatch :accounts_ssh_options_parser_string do
+ param 'String', :str
+ end
+
+ def accounts_ssh_options_parser_string(str)
+ words = []
+ field = ''
+ str.scan(%r{\G\,*(?>([^\,\\\'\"]+)|'([^\']*)'|("(?:[^\"\\]|\\.)*")|(\\.?)|(\S))(\,|\z)?}m) do |word, sq, dq, esc, garbage, sep|
+ raise ArgumentError, _('Unmatched double quote: %{str_inspect}') % { str_inspect: str.inspect } if garbage
+
+ field += (word || sq || dq || esc.gsub(%r{\\(.)}, '\\1'))
+ field.gsub(%r{\\=}, '\\=\"')
+ if sep
+ words << field
+ field = ''
+ end
+ end
+ words
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/home_dir.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/home_dir.pp
new file mode 100644
index 000000000..4e515f09b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/home_dir.pp
@@ -0,0 +1,146 @@
+# @summary
+# This resource specifies how home directories are managed.
+#
+# @param ensure
+# Specifies whether the user, its primary group, homedir, and ssh keys should
+# exist. Valid values are 'present' and 'absent'. Note that when a user is
+# created, a group with the same name as the user is also created.
+#
+# @param bash_profile_content
+# The content to place in the user's ~/.bash_profile file. Mutually exclusive
+# to bash_profile_source.
+#
+# @param bash_profile_source
+# A source file containing the content to place in the user's ~/.bash_profile
+# file. Mutually exclusive to bash_profile_content.
+#
+# @param bashrc_content
+# The content to place in the user's ~/.bashrc file. Mutually exclusive to
+# bashrc_source.
+#
+# @param bashrc_source
+# A source file containing the content to place in the user's ~/.bashrc file.
+# Mutually exclusive to bashrc_content.
+#
+# @param forward_content
+# The content to place in the user's ~/.forward file. Mutually exclusive to
+# forward_source.
+#
+# @param forward_source
+# A source file containing the content to place in the user's ~/.forward file.
+# Mutually exclusive to forward_content.
+#
+# @param group
+# Name of the user's primary group.
+#
+# @param managevim
+# Specifies whether or not the .vim folder should be created within the
+# managed account's home directory.
+#
+# @param mode
+# Manages the user's home directory permission mode. Valid values are in octal
+# notation.
+#
+# @param name
+# Path of the home directory that is being managed.
+#
+# @param user
+# Name of the user that owns all of the files being created.
+#
+# @api private
+#
+define accounts::home_dir (
+ Enum['absent','present'] $ensure = 'present',
+ Optional[String] $bash_profile_content = undef,
+ Optional[Stdlib::Filesource] $bash_profile_source = undef,
+ Optional[String] $bashrc_content = undef,
+ Optional[Stdlib::Filesource] $bashrc_source = undef,
+ Optional[String] $forward_content = undef,
+ Optional[Stdlib::Filesource] $forward_source = undef,
+ Optional[Accounts::User::Name] $group = undef,
+ Boolean $managevim = true,
+ Optional[Stdlib::Filemode] $mode = undef,
+ Optional[Accounts::User::Name] $user = undef,
+) {
+ assert_type(Stdlib::Unixpath, $name)
+ if $ensure == 'absent' {
+ fail('To remove home directories, use the `file` resource.')
+ } else {
+ assert_type(Accounts::User::Name, $group)
+ assert_type(Accounts::User::Name, $user)
+ # Solaris homedirs are managed in zfs by `useradd -m`. If the directory
+ # does not yet exist then we can't predict how it should be created, but we
+ # should still manage the user/group/mode
+ file { $name:
+ ensure => directory,
+ owner => $user,
+ group => $group,
+ mode => $mode,
+ }
+
+ if $managevim {
+ file { "${name}/.vim":
+ ensure => directory,
+ owner => $user,
+ group => $group,
+ mode => '0700',
+ }
+ }
+
+ if $bashrc_content or $bashrc_source {
+ file { "${name}/.bashrc":
+ ensure => file,
+ owner => $user,
+ group => $group,
+ mode => '0644',
+ }
+ if $bashrc_content {
+ File["${name}/.bashrc"] {
+ content => $bashrc_content,
+ }
+ }
+ if $bashrc_source {
+ File["${name}/.bashrc"] {
+ source => $bashrc_source,
+ }
+ }
+ }
+ if $bash_profile_content or $bash_profile_source {
+ file { "${name}/.bash_profile":
+ ensure => file,
+ owner => $user,
+ group => $group,
+ mode => '0644',
+ }
+ if $bash_profile_content {
+ File["${name}/.bash_profile"] {
+ content => $bash_profile_content,
+ }
+ }
+ if $bash_profile_source {
+ File["${name}/.bash_profile"] {
+ source => $bash_profile_source,
+ }
+ }
+ }
+
+ if $forward_content or $forward_source {
+ file { "${name}/.forward":
+ ensure => file,
+ owner => $user,
+ group => $group,
+ mode => '0644',
+ }
+ if $forward_content {
+ File["${name}/.forward"] {
+ content => $forward_content,
+ }
+ }
+ if $forward_source {
+ File["${name}/.forward"] {
+ source => $forward_source,
+ }
+ }
+ }
+ }
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/init.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/init.pp
new file mode 100644
index 000000000..f441ec613
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/init.pp
@@ -0,0 +1,27 @@
+# @summary
+# This class auto-creates user and group resources from hiera data.
+#
+# @param group_defaults
+# Hash of default attributes for group resources managed by this class.
+#
+# @param group_list
+# Hash of group resources for this class to manage. The hash is keyed by
+# group name.
+#
+# @param user_defaults
+# Hash of default attributes for accounts::user resources managed by this
+# class.
+#
+# @param user_list
+# Hash of accounts::user resources for this class to manage. The hash is
+# keyed by user name.
+#
+class accounts (
+ Accounts::Group::Resource $group_defaults = {},
+ Accounts::Group::Hash $group_list = {},
+ Accounts::User::Resource $user_defaults = {},
+ Accounts::User::Hash $user_list = {},
+) {
+ ensure_resources('group', $group_list, $group_defaults)
+ ensure_resources('accounts::user', $user_list, $user_defaults)
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/key_management.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/key_management.pp
new file mode 100644
index 000000000..01a063921
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/key_management.pp
@@ -0,0 +1,113 @@
+# @summary
+# This resource specifies where ssh keys are managed.
+#
+# @param user
+# User that owns all of the files being created.
+#
+# @param ensure
+# Specifies whether the key will be added ('present') or removed ('absent').
+#
+# @param group
+# Name of the user's primary group.
+#
+# @param purge_user_home
+# Whether to force recurse remove user home directories when removing a user.
+#
+# @param sshkey_custom_path
+# Path to custom file for ssh key management.
+#
+# @param sshkey_group
+# Specifies the group of the ssh key file.
+#
+# @param sshkey_owner
+# Specifies the owner of the ssh key file.
+#
+# @param sshkey_mode
+# Specifies the mode of the ssh key file.
+#
+# @param sshkeys
+# List of ssh keys to be added for this user in this directory.
+#
+# @param user_home
+# Specifies the path to the user's home directory.
+#
+# @api private
+#
+define accounts::key_management (
+ Accounts::User::Name $user,
+ Enum['absent','present'] $ensure = 'present',
+ Optional[Accounts::User::Name] $group = undef,
+ Boolean $purge_user_home = false,
+ Optional[Stdlib::Unixpath] $sshkey_custom_path = undef,
+ Accounts::User::Name $sshkey_group = $group,
+ Accounts::User::Name $sshkey_owner = $user,
+ Variant[Integer[0],String] $sshkey_mode = '0600',
+ Array[String] $sshkeys = [],
+ Optional[Stdlib::Unixpath] $user_home = undef,
+) {
+ if $user_home {
+ $sshkey_dotdir = "${user_home}/.ssh"
+ }
+
+ if $sshkey_custom_path != undef {
+ $key_file = $sshkey_custom_path.sprintf($user)
+ } elsif $user_home {
+ $key_file = "${sshkey_dotdir}/authorized_keys"
+ } else {
+ err('Either user_home or sshkey_custom_path must be specified')
+ }
+
+ if $ensure == 'present' {
+ file { $key_file:
+ ensure => 'file',
+ owner => $sshkey_owner,
+ group => $sshkey_group,
+ mode => $sshkey_mode,
+ }
+ if $user_home {
+ file { $sshkey_dotdir:
+ ensure => 'directory',
+ owner => $user,
+ group => $group,
+ mode => '0700',
+ }
+ }
+ if $sshkey_custom_path != undef {
+ $sshkey_require = File[$key_file]
+ } else {
+ $sshkey_require = File[$sshkey_dotdir]
+ }
+ $sshkey_before = undef
+ } else {
+ if $purge_user_home and $user_home {
+ file { $sshkey_dotdir:
+ ensure => 'absent',
+ before => User[$user],
+ recurse => true,
+ force => true,
+ }
+ $sshkey_before = [File[$key_file], File[$sshkey_dotdir]]
+ } else {
+ $sshkey_before = File[$key_file]
+ }
+ file { $key_file:
+ ensure => 'absent',
+ before => User[$user],
+ }
+ $sshkey_require = undef
+ }
+
+ if $sshkeys != [] {
+ $sshkeys.each |$sshkey| {
+ accounts::manage_keys { "${sshkey} for ${user}":
+ ensure => $ensure,
+ keyspec => $sshkey,
+ user => $user,
+ key_owner => $sshkey_owner,
+ key_file => $key_file,
+ require => $sshkey_require,
+ before => $sshkey_before,
+ }
+ }
+ }
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/manage_keys.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/manage_keys.pp
new file mode 100644
index 000000000..13907c028
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/manage_keys.pp
@@ -0,0 +1,58 @@
+# @summary
+# This resource manages ssh keys for a user.
+#
+# @param key_file
+# Specifies the path of the ssh key file.
+#
+# @param keyspec
+# Specifies the content of the ssh key file.
+#
+# @param user
+# Specifies the ssh login username.
+#
+# @param ensure
+# Specifies whether the keys will be added ('present') or removed ('absent').
+#
+# @param key_owner
+# Specifies the owner of the ssh key file.
+#
+# @api private
+#
+define accounts::manage_keys (
+ Stdlib::Unixpath $key_file,
+ String $keyspec,
+ Accounts::User::Name $user,
+ Enum['absent','present'] $ensure = 'present',
+ Accounts::User::Name $key_owner = $user,
+) {
+ $key_def = accounts_ssh_authorized_keys_line_parser($keyspec)
+ if (! $key_def) {
+ err("Could not interpret SSH key definition: '${keyspec}'")
+ }
+ else {
+ if (! empty($key_def[0])) {
+ $key_options = accounts_ssh_options_parser($key_def[0])
+ } else {
+ $key_options = undef
+ }
+ $key_type = $key_def[1]
+ $key_content = $key_def[2]
+ $key_md5 = md5($key_def[2])
+ $key_name = "${key_def[3]}_${key_md5}"
+
+ $key_title = "${user}_${key_type}_${key_name}"
+
+ if $ensure == 'absent' {
+ Ssh_authorized_key[$key_title] -> User[$user]
+ }
+
+ ssh_authorized_key { $key_title:
+ ensure => $ensure,
+ user => $key_owner,
+ key => $key_content,
+ type => $key_type,
+ options => $key_options,
+ target => $key_file,
+ }
+ }
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/user.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/user.pp
new file mode 100644
index 000000000..5b2329900
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/user.pp
@@ -0,0 +1,368 @@
+# @summary
+# This resource manages the user, group, vim/, .ssh/, .bash_profile, .bashrc,
+# homedir, .ssh/authorized_keys files, and directories.
+#
+# @example Basic usage
+# accounts::user { 'bob':
+# uid => '4001',
+# gid => '4001',
+# group => 'staff',
+# shell => '/bin/bash',
+# password => '!!',
+# locked => false,
+# }
+#
+# @param ensure
+# Specifies whether the user, its primary group, homedir, and ssh keys should
+# exist. Valid values are 'present' and 'absent'. Note that when a user is
+# created, a group with the same name as the user is also created.
+#
+# @param allowdupe
+# Whether to allow duplicate UIDs. By default false
+#
+# @param bash_profile_content
+# The content to place in the user's ~/.bash_profile file. Mutually exclusive
+# to bash_profile_source.
+#
+# @param bash_profile_source
+# A source file containing the content to place in the user's ~/.bash_profile
+# file. Mutually exclusive to bash_profile_content.
+#
+# @param bashrc_content
+# The content to place in the user's ~/.bashrc file. Mutually exclusive to
+# bashrc_source.
+#
+# @param bashrc_source
+# A source file containing the content to place in the user's ~/.bashrc file.
+# Mutually exclusive to bashrc_content.
+#
+# @param comment
+# A comment describing or regarding the user.
+#
+# @param create_group
+# Specifies if you want to create a group with the user's name.
+#
+# @param expiry
+# Specifies the date the user account expires on. Valid values: YYYY-MM-DD
+# date format, or 'absent' to remove expiry date.
+#
+# @param forcelocal
+# Specifies whether you want to manage a local user/group that is also managed
+# by a network name service.
+#
+# @param forward_content
+# The content to place in the user's ~/.forward file. Mutually exclusive to
+# forward_source.
+#
+# @param forward_source
+# A source file containing the content to place in the user's ~/.forward file.
+# Mutually exclusive to forward_content.
+#
+# @param gid
+# Specifies the gid of the user's primary group. Must be specified
+# numerically.
+#
+# @param group
+# Specifies the name of the user's primary group. By default, this uses a
+# group named the same as user name
+#
+# @param groups
+# Specifies the user's group memberships.
+#
+# @param home
+# Specifies the path to the user's home directory.
+#
+# - Linux, non-root user: '/home/$name'
+#
+# - Linux, root user: '/root'
+#
+# - Solaris, non-root user: '/export/home/$name'
+#
+# - Solaris, root user: '/'
+#
+# @param home_mode
+# Manages the user's home directory permission mode. Valid values are in octal
+# notation, specified as a string. Defaults to undef, which creates a home
+# directory with 0700 permissions. It does not touch them if the directory
+# already exists. Keeping it undef also allows a user to manage their own
+# permissions. If home_mode is set, Puppet enforces the permissions on every
+# run.
+#
+# @param ignore_password_if_empty
+# Specifies whether an empty password attribute should be ignored. If set to true,
+# a password attribute that is defined but set to the empty string is ignored,
+# allowing the password to be managed outside of this Puppet module. If set to false,
+# it sets the password to an empty value.
+#
+# @param iterations
+# This is the number of iterations of a chained computation of the PBKDF2
+# password hash. This field is required for managing passwords on OS X >=
+# 10.8.
+#
+# @param locked
+# Specifies whether the account should be locked and the user prevented from
+# logging in. Set to true for users whose login privileges have been revoked.
+#
+# @param managehome
+# Specifies whether the user's home directory should be created when adding a
+# user.
+#
+# @param managevim
+# Specifies whether or not the .vim folder should be created within the
+# managed accounts home directory.
+#
+# @param membership
+# Establishes whether specified groups should be considered the complete list
+# (inclusive) or the minimum list (minimum) of groups to which the user
+# belongs. Valid values: 'inclusive', 'minimum'.
+#
+# @param name
+# Name of the user.
+#
+# @param password
+# The user's password, in whatever encrypted format the local machine
+# requires. Default: '!!', which prevents the user from logging in with a
+# password.
+#
+# @param password_max_age
+# Maximum number of days a password may be used before it must be changed.
+# Allows any integer from `0` to `99999`. See the
+# [`user`](https://puppet.com/docs/puppet/latest/types/user.html#user-attribute-password_max_age)
+# resource.
+#
+# @param purge_sshkeys
+# Whether keys not included in sshkeys should be removed from the user. If
+# purge_sshkeys is true and sshkeys is an empty array, all SSH keys will be
+# removed from the user.
+#
+# @param purge_user_home
+# Whether to force recurse remove user home directories when removing a user.
+# Defaults to false.
+#
+# @param salt
+# This is the 32-byte salt used to generate the PBKDF2 password used in OS X.
+# This field is required for managing passwords on OS X >= 10.8.
+#
+# @param shell
+# Manages the user shell.
+#
+# @param sshkey_custom_path
+# Custom location for ssh public key file.
+#
+# @param sshkey_group
+# Specifies the group of the sshkey file
+#
+# @param sshkey_owner
+# Specifies the owner of the sshkey file
+#
+# @param sshkey_mode
+# Specifies the mode of the sshkey file .ssh/authorized_keys.
+#
+# @param sshkeys
+# An array of SSH public keys associated with the user. These should be
+# complete public key strings that include the type, content and name of the
+# key, exactly as it would appear in its id_*.pub file, or with an optional
+# options string preceding the other components, as it would appear as an
+# entry in an authorized_keys file. Must be an array.
+#
+# Examples:
+#
+# - ssh-rsa AAAAB3NzaC1y... bob@example.com
+#
+# - from="myhost.example.com,192.168.1.1" ssh-rsa AAAAQ4ng... bob2@example.com
+#
+# Note that for multiple keys, the name component (the last) must be unique.
+#
+# @param system
+# Specifies if you want to create a system account.
+#
+# @param uid
+# Specifies the user's uid number. Must be specified numerically.
+#
+define accounts::user (
+ Enum['absent','present'] $ensure = 'present',
+ Boolean $allowdupe = false,
+ Optional[String] $bash_profile_content = undef,
+ Optional[Stdlib::Filesource] $bash_profile_source = undef,
+ Optional[String] $bashrc_content = undef,
+ Optional[Stdlib::Filesource] $bashrc_source = undef,
+ String $comment = $name,
+ Boolean $create_group = true,
+ Optional[Accounts::User::Expiry] $expiry = undef,
+ Optional[Boolean] $forcelocal = undef,
+ Optional[String] $forward_content = undef,
+ Optional[Stdlib::Filesource] $forward_source = undef,
+ Optional[Accounts::User::Uid] $gid = undef,
+ Accounts::User::Name $group = $name,
+ Array[Accounts::User::Name] $groups = [],
+ Optional[Stdlib::Unixpath] $home = undef,
+ Optional[Stdlib::Filemode] $home_mode = undef,
+ Boolean $ignore_password_if_empty = false,
+ Optional[Accounts::User::Iterations] $iterations = undef,
+ Boolean $locked = false,
+ Boolean $managehome = true,
+ Boolean $managevim = true,
+ Enum['inclusive','minimum'] $membership = 'minimum',
+ Variant[String, Sensitive[String]] $password = '!!',
+ Optional[Accounts::User::PasswordMaxAge] $password_max_age = undef,
+ Boolean $purge_sshkeys = false,
+ Boolean $purge_user_home = false,
+ Optional[String] $salt = undef,
+ Stdlib::Unixpath $shell = '/bin/bash',
+ Optional[Stdlib::Unixpath] $sshkey_custom_path = undef,
+ Optional[Accounts::User::Name] $sshkey_group = $group,
+ Optional[Accounts::User::Name] $sshkey_owner = $name,
+ Variant[Integer[0],String] $sshkey_mode = '0600',
+ Array[String] $sshkeys = [],
+ Boolean $system = false,
+ Optional[Accounts::User::Uid] $uid = undef,
+) {
+ assert_type(Accounts::User::Name, $name)
+
+ include accounts::user::defaults
+
+ $_home = $home ? {
+ undef => $name ? {
+ 'root' => $accounts::user::defaults::root_home,
+ default => $accounts::user::defaults::home_template.sprintf($name),
+ },
+ default => $home,
+ }
+
+ if $ensure == 'absent' {
+ user { $name:
+ ensure => 'absent',
+ forcelocal => $forcelocal,
+ home => $_home,
+ managehome => false, # Workaround for PUP-9706; see below.
+ }
+ # The core `user` resource will fail when removing users on Solaris if
+ # `ensure => 'absent', managhome => true` and the homedir does not exist.
+ # We therefore force `managehome => false` when `ensure => 'absent'`, and
+ # remove the homedir as a separate operation.
+ # See https://tickets.puppetlabs.com/browse/PUP-9706
+ if $purge_user_home {
+ file { $_home:
+ ensure => 'absent',
+ recurse => true,
+ force => true,
+ }
+ }
+ # End workaround.
+ User[$name] -> Group <| ensure == 'absent' |>
+ if $create_group {
+ # Only remove the group if it is the same as user name as it may be shared.
+ if $name == $group {
+ ensure_resource(
+ 'group',
+ $group,
+ { 'ensure' => 'absent',
+ 'forcelocal' => $forcelocal,
+ }
+ )
+ }
+ }
+ accounts::key_management { "${name}_key_management":
+ ensure => 'absent',
+ user => $name,
+ user_home => $_home,
+ sshkeys => $sshkeys,
+ sshkey_custom_path => $sshkey_custom_path,
+ sshkey_owner => $sshkey_owner,
+ sshkey_group => $sshkey_group,
+ purge_user_home => $purge_user_home,
+ }
+ } else {
+ # Check if user wants to create the group
+ if $create_group and ! defined(Group[$group]) {
+ Group[$group] -> User[$name]
+ ensure_resource(
+ 'group',
+ $group,
+ { ensure => 'present',
+ gid => $gid,
+ system => $system,
+ forcelocal => $forcelocal,
+ }
+ )
+ }
+ $_password = (($password =~ String and $password == '') and $ignore_password_if_empty) ? {
+ true => undef,
+ default => $password,
+ }
+ $_purge_sshkeys = ($purge_sshkeys and $sshkey_custom_path != undef) ? {
+ true => [String($sshkey_custom_path)],
+ default => $purge_sshkeys,
+ }
+ $_shell = $locked ? {
+ true => $accounts::user::defaults::locked_shell,
+ default => $shell,
+ }
+ user { $name:
+ ensure => 'present',
+ allowdupe => $allowdupe,
+ comment => String($comment),
+ expiry => $expiry,
+ forcelocal => $forcelocal,
+ gid => $group,
+ groups => $groups,
+ home => $_home,
+ iterations => $iterations,
+ managehome => $managehome,
+ membership => $membership,
+ password => $_password,
+ password_max_age => $password_max_age,
+ purge_ssh_keys => $_purge_sshkeys,
+ salt => $salt,
+ shell => $_shell,
+ system => $system,
+ uid => $uid,
+ }
+ if $managehome {
+ accounts::home_dir { $_home:
+ ensure => 'present',
+ mode => $home_mode,
+ managevim => $managevim,
+ bashrc_content => $bashrc_content,
+ bashrc_source => $bashrc_source,
+ bash_profile_content => $bash_profile_content,
+ bash_profile_source => $bash_profile_source,
+ forward_content => $forward_content,
+ forward_source => $forward_source,
+ user => $name,
+ group => $group,
+ require => [User[$name]],
+ }
+ accounts::key_management { "${name}_key_management":
+ ensure => 'present',
+ user => $name,
+ group => $group,
+ user_home => $_home,
+ sshkeys => $sshkeys,
+ sshkey_custom_path => $sshkey_custom_path,
+ sshkey_owner => $sshkey_owner,
+ sshkey_group => $sshkey_group,
+ sshkey_mode => $sshkey_mode,
+ purge_user_home => $purge_user_home,
+ require => Accounts::Home_dir[$_home],
+ }
+ } elsif $sshkeys != [] {
+ # We are not managing the user's home directory but we have specified a
+ # custom, non-home directory for the ssh keys.
+ if (($sshkey_custom_path != undef) and ($ensure == 'present')) {
+ accounts::key_management { "${name}_key_management":
+ ensure => 'present',
+ user => $name,
+ group => $group,
+ sshkeys => $sshkeys,
+ sshkey_owner => $sshkey_owner,
+ sshkey_group => $sshkey_group,
+ sshkey_mode => $sshkey_mode,
+ sshkey_custom_path => $sshkey_custom_path,
+ }
+ } else {
+ warning("ssh keys were passed for user ${name} but managehome is set to false; not managing user ssh keys")
+ }
+ }
+ }
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/manifests/user/defaults.pp b/modules/utilities/unix/system/accounts_newer/accounts/manifests/user/defaults.pp
new file mode 100644
index 000000000..a9dd704a8
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/manifests/user/defaults.pp
@@ -0,0 +1,19 @@
+# @summary
+# Load some user defaults from hiera data.
+#
+# @param home_template
+# The sprintf template used to determine a user's home directory.
+#
+# @param locked_shell
+# The shell assigned to locked user accounts.
+#
+# @param root_home
+# The home directory of the root user.
+#
+class accounts::user::defaults (
+ Stdlib::AbsolutePath $home_template = '/home/%s',
+ Stdlib::AbsolutePath $locked_shell = '/sbin/nologin',
+ Stdlib::AbsolutePath $root_home = '/root',
+) {
+ # Nothing to see here; move along.
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/metadata.json b/modules/utilities/unix/system/accounts_newer/accounts/metadata.json
new file mode 100644
index 000000000..072736f08
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/metadata.json
@@ -0,0 +1,96 @@
+{
+ "name": "puppetlabs-accounts",
+ "version": "7.2.0",
+ "author": "puppetlabs",
+ "summary": "Account management module.",
+ "license": "Apache-2.0",
+ "source": "https://github.com/puppetlabs/puppetlabs-accounts",
+ "project_page": "https://github.com/puppetlabs/puppetlabs-accounts",
+ "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+ "dependencies": [
+ {
+ "name": "puppetlabs/stdlib",
+ "version_requirement": ">= 5.0.0 < 9.0.0"
+ }
+ ],
+ "operatingsystem_support": [
+ {
+ "operatingsystem": "RedHat",
+ "operatingsystemrelease": [
+ "6",
+ "7",
+ "8",
+ "9"
+ ]
+ },
+ {
+ "operatingsystem": "CentOS",
+ "operatingsystemrelease": [
+ "7",
+ "8"
+ ]
+ },
+ {
+ "operatingsystem": "OracleLinux",
+ "operatingsystemrelease": [
+ "6",
+ "7"
+ ]
+ },
+ {
+ "operatingsystem": "Scientific",
+ "operatingsystemrelease": [
+ "6",
+ "7"
+ ]
+ },
+ {
+ "operatingsystem": "Debian",
+ "operatingsystemrelease": [
+ "9",
+ "10",
+ "11"
+ ]
+ },
+ {
+ "operatingsystem": "SLES",
+ "operatingsystemrelease": [
+ "15"
+ ]
+ },
+ {
+ "operatingsystem": "Ubuntu",
+ "operatingsystemrelease": [
+ "18.04",
+ "20.04"
+ ]
+ },
+ {
+ "operatingsystem": "Solaris",
+ "operatingsystemrelease": [
+ "11"
+ ]
+ },
+ {
+ "operatingsystem": "Rocky",
+ "operatingsystemrelease": [
+ "8"
+ ]
+ },
+ {
+ "operatingsystem": "AlmaLinux",
+ "operatingsystemrelease": [
+ "8"
+ ]
+ }
+ ],
+ "requirements": [
+ {
+ "name": "puppet",
+ "version_requirement": ">= 6.0.0 < 8.0.0"
+ }
+ ],
+ "template-url": "https://github.com/puppetlabs/pdk-templates.git#main",
+ "template-ref": "heads/main-0-g806810b",
+ "pdk-version": "2.3.0"
+}
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/provision.yaml b/modules/utilities/unix/system/accounts_newer/accounts/provision.yaml
new file mode 100644
index 000000000..db7842259
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/provision.yaml
@@ -0,0 +1,68 @@
+---
+default:
+ provisioner: docker
+ images:
+ - litmusimage/centos:7
+vagrant:
+ provisioner: vagrant
+ images:
+ - centos/7
+ - generic/ubuntu1804
+travis_deb:
+ provisioner: docker
+ images:
+ - litmusimage/debian:8
+ - litmusimage/debian:9
+ - litmusimage/debian:10
+travis_ub_6:
+ provisioner: docker
+ images:
+ - litmusimage/ubuntu:14.04
+ - litmusimage/ubuntu:16.04
+ - litmusimage/ubuntu:18.04
+ - litmusimage/ubuntu:20.04
+travis_el7:
+ provisioner: docker
+ images:
+ - litmusimage/centos:7
+ - litmusimage/oraclelinux:7
+ - litmusimage/scientificlinux:7
+travis_el8:
+ provisioner: docker
+ images:
+ - litmusimage/centos:8
+release_checks_6:
+ provisioner: abs
+ images:
+ - redhat-6-x86_64
+ - redhat-7-x86_64
+ - redhat-8-x86_64
+ - centos-6-x86_64
+ - centos-7-x86_64
+ - centos-8-x86_64
+ - oracle-6-x86_64
+ - oracle-7-x86_64
+ - scientific-6-x86_64
+ - scientific-7-x86_64
+ - debian-8-x86_64
+ - debian-9-x86_64
+ - debian-10-x86_64
+ - sles-15-x86_64
+ - ubuntu-1404-x86_64
+ - ubuntu-1604-x86_64
+ - ubuntu-1804-x86_64
+ - ubuntu-2004-x86_64
+release_checks_7:
+ provisioner: abs
+ images:
+ - redhat-7-x86_64
+ - redhat-8-x86_64
+ - centos-7-x86_64
+ - centos-8-x86_64
+ - oracle-7-x86_64
+ - debian-9-x86_64
+ - debian-10-x86_64
+ - scientific-7-x86_64
+ - sles-15-x86_64
+ - ubuntu-1804-x86_64
+ - ubuntu-2004-x86_64
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/readmes/README_ja_JP.md b/modules/utilities/unix/system/accounts_newer/accounts/readmes/README_ja_JP.md
new file mode 100644
index 000000000..73a8e84af
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/readmes/README_ja_JP.md
@@ -0,0 +1,151 @@
+# アカウント
+
+#### 目次
+1. [説明](#description)
+2. [セットアップ - アカウントを開始するにあたっての基本設定](#setup)
+3. [使用方法 - 設定オプションと追加機能](#usage)
+ * [ユーザアカウントの宣言](#declare-user-accounts)
+ * [ホームディレクトリのカスタマイズ](#customize-the-home-directory)
+ * [アカウントのロック](#lock-accounts)
+ * [SSHキーの管理](#manage-ssh-keys)
+4. [参考 - モジュールの機能と動作について](#reference)
+5. [制約事項 - OSの互換性など](#limitations)
+6. [開発 - モジュール貢献についてのガイド](#development)
+
+
+## 説明
+
+アカウントモジュールは、ログインアカウントとサービスアカウントに関連するリソースを管理します。
+
+このモジュールは、多くのUNIX/Linuxオペレーティングシステムで動作します。Microsoft Windowsプラットフォームでのアカウントの設定はサポートされていません。
+
+## セットアップ
+
+### アカウントの使用開始
+
+Puppetで管理されているノードのマニフェストで`accounts`クラスを宣言します。
+
+~~~puppet
+node default {
+ accounts::user { 'dan': }
+ accounts::user { 'morgan': }
+}
+~~~
+
+上記の例では、DanとMorganのアカウント、ホームディレクトリ、グループを作成しています。
+
+## 使用方法
+
+### ユーザアカウントの宣言
+
+~~~puppet
+accounts::user { 'bob':
+ uid => '4001',
+ gid => '4001',
+ group => 'staff',
+ shell => '/bin/bash',
+ password => '!!',
+ locked => false,
+}
+~~~
+
+### ホームディレクトリのカスタマイズ
+
+単純なbashrcおよびbash\ _profile rcファイルは、各アカウントのPuppetによって管理されます。これらのrcファイルは単純なエイリアスの追加、プロンプトの更新、パスへの~/binの追加を行い、(このモジュールでは管理されていない)次のファイルを以下の順序でソースします。
+
+ 1. `/etc/bashrc`
+ 2. `/etc/bashrc.puppet`
+ 3. `~/.bashrc.custom`
+
+アカウント所有者は、bashrc.customファイルを管理することでシェルをカスタマイズできます。さらに、システム管理者は、 '/etc/bashrc.puppet'ファイルを管理することで、bashシェルを持つすべてのアカウントに影響を与えるプロファイルの変更を行うことができます。
+
+電子メールフォワードをインストールするには、 `forward_content`または` forward_source`パラメータを使って `.forward`ファイルを設定します。
+
+### アカウントのロック
+
+アカウントの`locked`パラメータをtrueに設定して、アカウントをロックします。
+
+例:
+
+~~~puppet
+accounts::user { 'villain':
+ comment => 'Bad Person',
+ locked => true
+}
+~~~
+
+アカウントモジュールは、Puppetが管理しているシステムに適した無効なシェルにアカウントを設定し、ユーザがそのアカウントにアクセスしようとすると次のメッセージを表示します。
+
+~~~
+$ ssh villain@centos56
+This account is currently not available.
+Connection to 172.16.214.129 closed.
+~~~
+
+### SSHキーの管理
+
+`accounts::user`定義型の`sshkeys`属性でSSHキーを管理します。このパラメータは、パブリックキーコンテンツの配列を文字列として受け取ります。
+
+例:
+
+~~~puppet
+accounts::user { 'jeff':
+ comment => 'Jeff McCune',
+ groups => [
+ 'admin',
+ 'sudonopw',
+ ],
+ uid => '1112',
+ gid => '1112',
+ sshkeys => [
+ 'ssh-rsa AAAAB3Nza...== jeff@puppetlabs.com',
+ 'ssh-dss AAAAB3Nza...== jeff@metamachine.net',
+ ],
+}
+~~~
+
+このモジュールは、カスタムロケーションでのSSHキーの配置をサポートしています。`accounts::user` 定義型の`sshkey_custom_path`属性の値を指定すると、モジュールは指定されたファイルにキーを配置します。このモジュールはフルパスではなく、指定されたファイルのみを管理します。`purge_sshkeys`をtrueに設定してカスタムパスを設定した場合、カスタムパスのSSHキーのみがパージされます。
+
+例:
+
+~~~puppet
+accounts::user { 'gerrard':
+ sshkey_custom_path => '/var/lib/ssh/gerrard/authorized_keys',
+ shell => '/bin/zsh',
+ comment => 'Gerrard Geldenhuis',
+ groups => [
+ 'engineering',
+ 'automation',
+ ],
+ uid => '1117',
+ gid => '1117',
+ sshkeys => [
+ 'ssh-rsa AAAAB9Aza...== gerrard@dirtyfruit.co.uk',
+ 'ssh-dss AAAAB9Aza...== gerrard@dojo.training',
+ ],
+ password => '!!',
+}
+~~~
+
+`sshkey_custom_path`の設定は、通常、sshd設定ファイルの`AuthorizedKeysFile /var/lib/ssh/%u/authorized_keys`の設定に関連します。
+
+## リファレンス
+
+[REFERENCE.md](https://github.com/puppetlabs/puppetlabs-accounts/blob/main/REFERENCE.md)を参照してください。
+
+## 制約事項
+
+ サポートされているオペレーティングシステムの一覧については、[metadata.json](https://github.com/puppetlabs/puppetlabs-accounts/blob/main/metadata.json)を参照してください。
+
+### pe\_accountsからの変更
+
+アカウントモジュールは、PEバージョン2015.2以前に同梱されているpe\_accountsモジュールの置き換えとして設計されています。変更の一部には、基本クラスの削除、検証の改善、ユーザのホームディレクトリで管理すべきファイルと管理すべきではないファイルに関する柔軟性の強化が含まれます。
+
+例えば、.bashrcと.bash\_profileの各ファイルはデフォルトでは管理されませんが、`bashrc_content`パラメータと`bash_profile_content`パラメータを使ってカスタムコンテンツを渡すことができます。pe\_accountsで管理されているこれらの2つのファイルのコンテンツは、`bashrc_content => file('accounts/shell/bashrc')`と`bash_profile_content => file('accounts/shell/bash_profile')`を`accounts::user`定義型に渡すことで引き続き使用できます.
+
+
+## 開発
+
+本モジュールで問題が発生した場合、またはリクエストしたい機能がある場合、[チケットを送信](https://tickets.puppetlabs.com/browse/MODULES/)してください。
+
+本モジュールの導入時に問題がある場合は、[サポートにお問い合わせ](http://puppetlabs.com/services/customer-support)ください。
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/secgen_metadata.xml b/modules/utilities/unix/system/accounts_newer/accounts/secgen_metadata.xml
new file mode 100644
index 000000000..aa4d3b111
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/secgen_metadata.xml
@@ -0,0 +1,26 @@
+
+
+
+ User account service
+ Puppet Labs
+ Jason Keighley
+ Apache v2
+ User account creation and modification
+
+ system
+ puppet_import
+ linux
+
+
+ https://forge.puppet.com/puppetlabs/accounts
+
+
+ .*/bases/.*wheezy.*
+
+
+ .*/bases/.*stretch.*
+
+
+
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/accounts_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/accounts_spec.rb
new file mode 100644
index 000000000..640859f01
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/accounts_spec.rb
@@ -0,0 +1,519 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+test_key = 'AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz'\
+ '4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKL'\
+ 'v6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7P'\
+ 'tixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJ'\
+ 'nAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96h'\
+ 'rucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ=='
+
+hd_defaults = {
+ 'accounts::user_defaults' => {
+ 'home_mode' => '0700',
+ },
+}
+
+hd_group = {
+ 'accounts::group_defaults' => {
+ 'ensure' => 'present',
+ 'system' => true,
+ },
+ 'accounts::group_list' => {
+ 'staff' => {
+ 'gid' => 1234,
+ },
+ },
+}
+
+hd_group_change = hd_group.merge(
+ 'accounts::group_list' => {
+ 'staff' => {
+ 'gid' => 1235,
+ },
+ },
+)
+
+hd_accounts_define = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'groups' => ['root'],
+ 'password' => 'hi',
+ 'password_max_age' => 60,
+ 'shell' => '/bin/true',
+ 'home' => '/test/hunner',
+ 'managevim' => false,
+ 'bashrc_source' => 'puppet:///modules/accounts/shell/bashrc',
+ 'bash_profile_source' => 'puppet:///modules/accounts/shell/bash_profile',
+ 'sshkeys' => [
+ "ssh-rsa #{test_key} vagrant",
+ 'command="/bin/echo Hello",from="myhost.exapmle.com,192.168.1.1" '\
+ "ssh-rsa #{test_key} vagrant2",
+ ],
+ },
+ },
+)
+
+hd_accounts_with_custom_key_path_define = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'sshkey_custom_path' => '/test/sshkeys/hunner',
+ 'sshkey_owner' => 'root',
+ 'sshkey_group' => 'root',
+ 'groups' => ['root'],
+ 'password' => 'hi',
+ 'password_max_age' => 60,
+ 'shell' => '/bin/true',
+ 'home' => '/test/hunner',
+ 'managevim' => false,
+ 'bashrc_source' => 'puppet:///modules/accounts/shell/bashrc',
+ 'bash_profile_source' => 'puppet:///modules/accounts/shell/bash_profile',
+ 'sshkeys' => [
+ "ssh-rsa #{test_key} vagrant",
+ 'command="/bin/echo Hello",from="myhost.exapmle.com,192.168.1.1" '\
+ "ssh-rsa #{test_key} vagrant2",
+ ],
+ },
+ },
+)
+
+hd_without_managehome = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'managehome' => false,
+ 'sshkeys' => [
+ "ssh-rsa #{test_key} vagrant",
+ ],
+ },
+ },
+)
+
+hd_with_managevim = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'groups' => ['root'],
+ 'password' => 'hi',
+ 'shell' => '/bin/true',
+ 'home' => '/test/hunner',
+ 'home_mode' => '0700',
+ 'managevim' => true,
+ 'bashrc_source' => 'puppet:///modules/accounts/shell/bashrc',
+ 'bash_profile_source' => 'puppet:///modules/accounts/shell/bash_profile',
+ 'sshkeys' => [
+ "ssh-rsa #{test_key} vagrant",
+ 'from="myhost.example.com,192.168.1.1" '\
+ "ssh-rsa #{test_key} vagrant2",
+ ],
+ },
+ },
+)
+
+hd_locked_user = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'locked' => true,
+ },
+ },
+)
+
+hd_custom_group_name = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'first.last' => {
+ 'group' => 'staff',
+ 'password' => '!!',
+ 'home' => '/test/first.last',
+ },
+ },
+)
+
+hd_create_group_false = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'grp_flse' => {
+ 'group' => 'newgrp_1',
+ 'create_group' => false,
+ 'home' => '/test/grp_flse',
+ },
+ },
+)
+
+hd_create_group_true = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'grp_true' => {
+ 'group' => 'newgrp_2',
+ 'create_group' => true,
+ 'home' => '/test/grp_true',
+ },
+ },
+)
+
+hd_ignore_user_first_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'ignore_user' => {
+ 'group' => 'staff',
+ 'password' => 'foo',
+ },
+ },
+)
+
+hd_ignore_user_second_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'ignore_user' => {
+ 'group' => 'staff',
+ 'password' => '',
+ 'ignore_password_if_empty' => true,
+ },
+ },
+)
+
+hd_no_ignore_user_first_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'no_ignore_user' => {
+ 'group' => 'staff',
+ 'password' => 'foo',
+ },
+ },
+)
+
+hd_no_ignore_user_second_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'no_ignore_user' => {
+ 'group' => 'staff',
+ 'password' => '',
+ 'ignore_password_if_empty' => false,
+ },
+ },
+)
+
+hd_specd_user_first_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'specd_user' => {
+ 'group' => 'staff',
+ 'password' => 'foo',
+ },
+ },
+)
+
+hd_specd_user_second_run = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'specd_user' => {
+ 'group' => 'staff',
+ 'password' => 'bar',
+ 'ignore_password_if_empty' => true,
+ },
+ },
+)
+
+hd_user_with_duplicate_id = hd_defaults.merge(
+ 'accounts::user_list' => {
+ 'duplicate_user1' => {
+ 'allowdupe' => true,
+ 'uid' => '1234',
+ 'sshkey_owner' => 'duplicate_user1',
+ },
+ 'duplicate_user2' => {
+ 'allowdupe' => true,
+ 'uid' => 1234,
+ 'sshkey_owner' => 'duplicate_user1',
+ },
+ },
+)
+
+hd_delete_accounts = {
+ 'accounts::group_defaults' => {
+ 'ensure' => 'absent',
+ },
+ 'accounts::group_list' => {
+ 'newgrp_1' => {},
+ 'newgrp_2' => {},
+ 'staff' => {},
+ },
+ 'accounts::user_defaults' => {
+ 'ensure' => 'absent',
+ 'create_group' => true,
+ 'purge_user_home' => true,
+ },
+ 'accounts::user_list' => {
+ 'hunner' => {
+ 'home' => '/test/hunner',
+ 'sshkey_custom_path' => '/test/sshkeys/hunner',
+ 'sshkey_owner' => 'root',
+ 'sshkey_group' => 'root',
+ 'sshkeys' => [
+ "ssh-rsa #{test_key} vagrant",
+ "ssh-rsa #{test_key} vagrant2",
+ ],
+ },
+ 'first.last' => {
+ 'home' => '/test/first.last',
+ },
+ 'grp_flse' => {
+ 'home' => '/test/grp_flse',
+ },
+ 'grp_true' => {
+ 'home' => '/test/grp_true',
+ },
+ 'ignore_user' => {},
+ 'no_ignore_user' => {},
+ 'specd_user' => {},
+ 'duplicate_user1' => {},
+ 'duplicate_user2' => {},
+ },
+}
+
+pp_manifest = <<-PUPPETCODE
+ file { '/test':
+ ensure => 'directory',
+ before => Class['accounts'],
+ }
+ include ::accounts
+PUPPETCODE
+
+pp_manifest_custom_sshkey = <<-PUPPETCODE
+ file { '/test':
+ ensure => 'directory',
+ before => Class['accounts'],
+ }
+ file { '/test/sshkeys':
+ ensure => 'directory',
+ before => Class['accounts'],
+ }
+ include ::accounts
+PUPPETCODE
+
+pp_cleanup = <<-PUPPETCODE
+ include ::accounts
+ file { '/test':
+ ensure => 'absent',
+ force => true,
+ }
+PUPPETCODE
+
+describe 'accounts invoke', unless: UNSUPPORTED_PLATFORMS.include?(os[:family]) do
+ describe 'group test' do
+ it 'creates group with specified gid' do
+ set_hieradata(hd_group)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(group('staff')).to exist
+ expect(group('staff')).to have_gid 1234
+ end
+ it 'changes existing group id' do
+ set_hieradata(hd_group)
+ apply_manifest(pp_manifest, catch_failures: true)
+ set_hieradata(hd_group_change)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(group('staff')).to exist
+ expect(group('staff')).to have_gid 1235
+ end
+ end
+
+ describe 'main tests' do
+ it 'creates groups of matching names, assigns non-matching group, '\
+ 'manages homedir, manages other properties, gives key, '\
+ 'makes dotfiles, managevim false' do
+ set_hieradata(hd_accounts_define)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('hunner')).to exist
+ expect(user('hunner')).to belong_to_group 'hunner'
+ expect(user('hunner')).to belong_to_group 'root'
+ expect(user('hunner')).to have_login_shell '/bin/true'
+ expect(user('hunner')).to have_home_directory '/test/hunner'
+ expect(user('hunner')).to contain_password 'hi' unless os[:family] == 'solaris'
+ expect(user('hunner').maximum_days_between_password_change).to match 60
+
+ expect(file('/test/hunner')).to be_directory
+ expect(file('/test/hunner')).to be_mode 700
+ expect(file('/test/hunner')).to be_owned_by 'hunner'
+ expect(file('/test/hunner')).to be_grouped_into 'hunner'
+
+ expect(file('/test/hunner/.bashrc')).to be_file
+ expect(file('/test/hunner/.bashrc').content).to match %r{managed by Puppet}
+
+ expect(file('/test/hunner/.bash_profile')).to be_file
+ expect(file('/test/hunner/.bash_profile').content).to match %r{Get the aliases and functions}
+
+ expect(file('/test/hunner/.vim')).not_to exist
+ end
+ end
+
+ describe 'main tests with custom key path' do
+ it 'manages ssh key in a separate directory' do
+ set_hieradata(hd_accounts_with_custom_key_path_define)
+ apply_manifest(pp_manifest_custom_sshkey, catch_failures: true)
+
+ expect(user('hunner')).to exist
+
+ expect(file('/test/hunner')).to be_directory
+ expect(file('/test/hunner')).to be_mode 700
+ expect(file('/test/hunner')).to be_owned_by 'hunner'
+ expect(file('/test/hunner')).to be_grouped_into 'hunner'
+
+ expect(file('/test/hunner/.ssh/authorized_key')).not_to exist
+ expect(file('/test/sshkeys/hunner')).to be_file
+ expect(file('/test/sshkeys/hunner')).to be_owned_by 'root'
+ end
+ end
+
+ describe 'warn for sshkeys without managehome' do
+ it 'creates groups of matching names, assigns non-matching group, '\
+ 'manages homedir, manages other properties, gives key, '\
+ 'makes dotfiles' do
+ set_hieradata(hd_without_managehome)
+ apply_manifest(pp_manifest, catch_failures: true) do |r|
+ expect(r.stderr).to match(%r{Warning:.*ssh keys were passed for user hunner})
+ end
+ end
+ end
+
+ describe 'managevim set to true' do
+ it 'creates .vim file' do
+ set_hieradata(hd_with_managevim)
+ apply_manifest(pp_manifest, catch_failures: true)
+ expect(file('/test/hunner/.vim')).to be_directory
+ end
+ end
+
+ describe 'locking users' do
+ let(:login_shell) do
+ case os[:family]
+ when %r{debian|ubuntu}
+ '/usr/sbin/nologin'
+ when 'solaris'
+ '/usr/bin/false'
+ else
+ '/sbin/nologin'
+ end
+ end
+
+ it 'locks a user' do
+ set_hieradata(hd_locked_user)
+ apply_manifest(pp_manifest, catch_failures: true)
+ expect(user('hunner')).to have_login_shell login_shell
+ end
+ end
+
+ describe 'create user with custom group name' do
+ it 'creates group of matching names, assigns non-matching group, '\
+ 'manages homedir' do
+ set_hieradata(hd_custom_group_name)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('first.last')).to exist
+ expect(user('first.last')).to belong_to_group 'staff'
+ expect(user('first.last')).to have_home_directory '/test/first.last'
+
+ expect(file('/test/first.last')).to be_directory
+ expect(file('/test/first.last')).to be_mode 700
+ expect(file('/test/first.last')).to be_owned_by 'first.last'
+ expect(file('/test/first.last')).to be_grouped_into 'staff'
+ end
+ end
+
+ describe 'group set to false does not create group' do
+ it 'does not create group' do
+ set_hieradata(hd_create_group_false)
+ apply_manifest(pp_manifest, expect_failures: true) do |r|
+ expect(r.stderr).to match(%r{(.*group '?newgrp_1'? does not exist.*|.*Unknown group `?newgrp_1'?.*)})
+ end
+ expect(user('grp_flse')).not_to exist
+ expect(user('grp_flse')).not_to belong_to_group 'new_group_1'
+ end
+ end
+
+ describe 'group set to true creates group' do
+ it 'creates group' do
+ set_hieradata(hd_create_group_true)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('grp_true')).to exist
+ expect(user('grp_true')).to belong_to_group 'newgrp_2'
+ end
+ end
+
+ # Solaris does not offer a means of testing the password
+ describe 'ignore password if ignore set to true', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group,'\
+ 'empty password, ignore true, ignores password' do
+ set_hieradata(hd_ignore_user_first_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+ set_hieradata(hd_ignore_user_second_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('ignore_user')).to exist
+ expect(user('ignore_user')).to contain_password 'foo'
+ end
+ end
+
+ # Solaris does not offer a means of testing the password
+ describe 'do not ignore password if ignore set to false', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group,'\
+ 'empty password, ignore false, should not ignore password' do
+ set_hieradata(hd_no_ignore_user_first_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+ set_hieradata(hd_no_ignore_user_second_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('no_ignore_user')).to exist
+ expect(user('no_ignore_user')).to contain_password ''
+ end
+ end
+
+ describe 'do not ignore password if set and ignore set to true', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group, '\
+ 'specify password, ignore, should not ignore password' do
+ set_hieradata(hd_specd_user_first_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+ set_hieradata(hd_specd_user_second_run)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('specd_user')).to exist
+ expect(user('specd_user')).to contain_password 'bar'
+ end
+ end
+
+ describe 'create duplicate users with same uid' do
+ it 'runs with no errors' do
+ set_hieradata(hd_user_with_duplicate_id)
+ apply_manifest(pp_manifest, catch_failures: true)
+
+ expect(user('duplicate_user1')).to exist
+ expect(user('duplicate_user1')).to have_uid 1234
+
+ expect(user('duplicate_user2')).to exist
+ expect(user('duplicate_user2')).to have_uid 1234
+ end
+ end
+
+ describe 'delete accounts' do
+ it 'removes users and groups' do
+ set_hieradata(hd_delete_accounts)
+ apply_manifest(pp_cleanup, catch_failures: true)
+
+ expect(file('/test')).not_to exist
+ expect(file('/home/ignore_user')).not_to exist
+ expect(file('/home/no_ignore_user')).not_to exist
+ expect(file('/home/specd_user')).not_to exist
+ expect(file('/home/duplicate_user1')).not_to exist
+ expect(file('/home/duplicate_user2')).not_to exist
+ expect(file('/test/sshkeys/hunner')).not_to exist
+ expect(user('hunner')).not_to exist
+ expect(user('first.last')).not_to exist
+ expect(user('grp_flse')).not_to exist
+ expect(user('grp_true')).not_to exist
+ expect(user('ignore_user')).not_to exist
+ expect(user('no_ignore_user')).not_to exist
+ expect(user('specd_user')).not_to exist
+ expect(user('duplicate_user1')).not_to exist
+ expect(user('duplicate_user2')).not_to exist
+ expect(group('staff')).not_to exist
+ expect(group('hunner')).not_to exist
+ expect(group('newgrp_1')).not_to exist
+ expect(group('newgrp_2')).not_to exist
+ expect(group('duplicate_user1')).not_to exist
+ expect(group('duplicate_user2')).not_to exist
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/user_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/user_spec.rb
new file mode 100644
index 000000000..c46c02cb7
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/acceptance/user_spec.rb
@@ -0,0 +1,405 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+test_key = 'AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8Hfd'\
+ 'OV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9W'\
+ 'hQ=='
+ecdsa_test_key = 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNlpEm6+RwCiQXgQAb0P1asEAxCJDVtm/YYyUbdSifCbri98fjs1C/03pm9yLRQ0W/S70S8AhDCMjVFA07WzjOQ='
+ecdsa_sk_test_key = 'AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBAjkGvdKC05udQc82xGWWSKHbmJyBoa/oCq+2FiU6udqQyx0uOEC3YZAjvygBSdIo5vCpDELqJxaNQGQEkeUyYYAAAAEc3NoOg=='
+
+pp_accounts_define = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['hunner'],
+ }
+ if $facts['puppetversion'][0] == '6' {
+ $key_test = [
+ 'ssh-rsa #{test_key} vagrant',
+ 'command="/bin/echo Hello",from="myhost.example.com,192.168.1.1" ssh-rsa #{test_key} vagrant2'
+ ]
+ }
+ else {
+ $key_test = [#{' '}
+ 'ssh-rsa #{test_key} vagrant',
+ 'command="/bin/echo Hello",from="myhost.example.com,192.168.1.1" ssh-rsa #{test_key} vagrant2',
+ 'ecdsa-sha2-nistp256 #{ecdsa_test_key} vagrant3',
+ 'sk-ecdsa-sha2-nistp256@openssh.com #{ecdsa_sk_test_key} vagrant4'
+ ]
+ }
+
+ accounts::user { 'hunner':
+ groups => ['root'],
+ password => 'hi',
+ shell => '/bin/true',
+ home => '/test/hunner',
+ home_mode => '0700',
+ managevim => false,
+ bashrc_content => file('accounts/shell/bashrc'),
+ bash_profile_content => file('accounts/shell/bash_profile'),
+ sshkeys => $key_test,
+ }
+PUPPETCODE
+
+pp_without_managehome = <<-PUPPETCODE
+ accounts::user { 'hunner':
+ managehome => false,
+ sshkeys => [
+ 'ssh-rsa #{test_key} vagrant',
+ ],
+ }
+PUPPETCODE
+
+pp_with_managevim = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['hunner'],
+ }
+ if $facts['puppetversion'][0] == '6' {
+ $key_test = [
+ 'ssh-rsa #{test_key} vagrant',
+ 'command="/bin/echo Hello",from="myhost.example.com,192.168.1.1" ssh-rsa #{test_key} vagrant2'
+ ]
+ }
+ else {
+ $key_test = [#{' '}
+ 'ssh-rsa #{test_key} vagrant',
+ 'command="/bin/echo Hello",from="myhost.example.com,192.168.1.1" ssh-rsa #{test_key} vagrant2',
+ 'ecdsa-sha2-nistp256 #{ecdsa_test_key} vagrant3',
+ 'sk-ecdsa-sha2-nistp256@openssh.com #{ecdsa_sk_test_key} vagrant4'
+ ]
+ }
+
+ accounts::user { 'hunner':
+ groups => ['root'],
+ password => 'hi',
+ shell => '/bin/true',
+ home => '/test/hunner',
+ home_mode => '0700',
+ managevim => true,
+ bashrc_content => file('accounts/shell/bashrc'),
+ bash_profile_content => file('accounts/shell/bash_profile'),
+ sshkeys => $key_test,
+ }
+PUPPETCODE
+
+pp_locked_user = <<-PUPPETCODE
+ accounts::user { 'hunner':
+ locked => true,
+ }
+PUPPETCODE
+
+pp_custom_group_name = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['first.last'],
+ }
+ accounts::user { 'first.last':
+ group => 'staff',
+ password => '!!',
+ home => '/test/first.last',
+ home_mode => '0700',
+ }
+PUPPETCODE
+
+pp_create_group_false = <<-PUPPETCODE
+ accounts::user { 'grp_flse':
+ group => 'newgrp_1',
+ create_group => false,
+ home => '/test/grp_flse',
+ }
+PUPPETCODE
+
+pp_create_group_true = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['grp_true'],
+ }
+ accounts::user { 'grp_true':
+ group => 'newgrp_2',
+ create_group => true,
+ home => '/test/grp_true',
+ }
+PUPPETCODE
+
+pp_ignore_user_first_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['ignore_user'],
+ }
+ accounts::user { 'ignore_user':
+ group => 'staff',
+ password => 'foo',
+ }
+PUPPETCODE
+
+pp_ignore_user_second_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['ignore_user'],
+ }
+ accounts::user { 'ignore_user':
+ group => 'staff',
+ password => '',
+ ignore_password_if_empty => true,
+ }
+PUPPETCODE
+
+pp_no_ignore_user_first_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['no_ignore_user'],
+ }
+ accounts::user { 'no_ignore_user':
+ group => 'staff',
+ password => 'foo',
+ }
+PUPPETCODE
+
+pp_no_ignore_user_second_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['no_ignore_user'],
+ }
+ accounts::user { 'no_ignore_user':
+ group => 'staff',
+ password => '',
+ ignore_password_if_empty => false,
+ }
+PUPPETCODE
+
+pp_specd_user_first_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['specd_user'],
+ }
+ accounts::user { 'specd_user':
+ group => 'staff',
+ password => 'foo',
+ }
+PUPPETCODE
+
+pp_specd_user_second_run = <<-PUPPETCODE
+ file { '/test':
+ ensure => directory,
+ before => Accounts::User['specd_user'],
+ }
+ accounts::user { 'specd_user':
+ group => 'staff',
+ password => 'bar',
+ ignore_password_if_empty => true,
+ }
+PUPPETCODE
+
+pp_archive_homedir_before_user_deletion = <<-PUPPETCODE
+ file { '/test/archives':
+ ensure => 'directory',
+ group => 'archiver',
+ mode => '0700',
+ owner => 'archiver',
+ }
+ exec { 'backup homedir of specd_user':
+ command => 'tar -czf /test/archives/specd_user.tar.gz specd_user',
+ creates => '/test/specd_user.tar.gz',
+ cwd => '/home',
+ path => '/bin',
+ require => File['/test/archives'],
+ }
+ accounts::user { 'specd_user':
+ ensure => 'absent',
+ purge_user_home => true,
+ require => Exec['backup homedir of specd_user'],
+ }
+ accounts::user { 'archiver':
+ ensure => 'present',
+ }
+PUPPETCODE
+
+pp_user_with_duplicate_uid = <<-PUPPETCODE
+ accounts::user { 'duplicate_user1':
+ allowdupe => true,
+ uid => '1234',
+ sshkey_owner => 'duplicate_user1',
+ }
+ accounts::user { 'duplicate_user2':
+ allowdupe => true,
+ uid => '1234',
+ sshkey_owner => 'duplicate_user1',
+ }
+PUPPETCODE
+
+pp_user_with_sensitive_password = <<-PUPPETCODE
+ accounts::user { 'sensitive_user':
+ password => Sensitive('bar'),
+ }
+PUPPETCODE
+
+pp_cleanup = <<-PUPPETCODE
+ file { '/test':
+ ensure => 'absent',
+ force => true,
+ }
+PUPPETCODE
+
+describe 'accounts::user define', unless: UNSUPPORTED_PLATFORMS.include?(os[:family]) do
+ after(:all) do
+ # Cleanup any files created to ensure tests can be ran multiple times
+ apply_manifest(pp_cleanup, catch_failures: true)
+ end
+
+ describe 'main tests' do
+ it 'creates groups of matching names, assigns non-matching group, manages homedir, manages other properties, gives key, makes dotfiles, managevim false' do
+ apply_manifest(pp_accounts_define, catch_failures: true)
+
+ expect(user('hunner')).to exist
+ expect(user('hunner')).to belong_to_group 'hunner'
+ expect(user('hunner')).to belong_to_group 'root'
+ expect(user('hunner')).to have_login_shell '/bin/true'
+ expect(user('hunner')).to have_home_directory '/test/hunner'
+ expect(user('hunner')).to contain_password 'hi' unless os[:family] == 'solaris'
+
+ expect(file('/test/hunner')).to be_directory
+ expect(file('/test/hunner')).to be_mode 700
+ expect(file('/test/hunner')).to be_owned_by 'hunner'
+ expect(file('/test/hunner')).to be_grouped_into 'hunner'
+
+ expect(file('/test/hunner/.bashrc')).to be_file
+ expect(file('/test/hunner/.bashrc').content).to match %r{managed by Puppet}
+
+ expect(file('/test/hunner/.bash_profile')).to be_file
+ expect(file('/test/hunner/.bash_profile').content).to match %r{Get the aliases and functions}
+
+ expect(file('/test/hunner/.vim')).not_to exist
+ end
+ end
+
+ describe 'warn for sshkeys without managehome' do
+ it 'creates groups of matching names, assigns non-matching group, manages homedir, manages other properties, gives key, makes dotfiles' do
+ apply_manifest(pp_without_managehome, catch_failures: true) do |r|
+ expect(r.stderr).to match(%r{Warning:.*ssh keys were passed for user hunner})
+ end
+ end
+ end
+
+ describe 'managevim set to true' do
+ it '.vim file will be created' do
+ apply_manifest(pp_with_managevim, catch_failures: true)
+ expect(file('/test/hunner/.vim')).to be_directory
+ end
+ end
+
+ describe 'locking users' do
+ let(:login_shell) do
+ case os[:family]
+ when %r{debian|ubuntu} # Are there Debian-related distros besides Ubuntu?
+ '/usr/sbin/nologin'
+ when 'solaris'
+ '/usr/bin/false'
+ else
+ '/sbin/nologin'
+ end
+ end
+
+ it 'locks a user' do
+ apply_manifest(pp_locked_user, catch_failures: true)
+ expect(user('hunner')).to have_login_shell login_shell
+ end
+ end
+
+ describe 'create user with custom group name' do
+ it 'creates group of matching names, assigns non-matching group, manages homedir' do
+ apply_manifest(pp_custom_group_name, catch_failures: true)
+
+ expect(user('first.last')).to exist
+ expect(user('first.last')).to belong_to_group 'staff'
+ expect(user('first.last')).to have_home_directory '/test/first.last'
+
+ expect(file('/test/first.last')).to be_directory
+ expect(file('/test/first.last')).to be_mode 700
+ expect(file('/test/first.last')).to be_owned_by 'first.last'
+ expect(file('/test/first.last')).to be_grouped_into 'staff'
+ end
+ end
+
+ describe 'group set to false does not create group' do
+ it 'does not create group' do
+ apply_manifest(pp_create_group_false, expect_failures: true) do |r|
+ expect(r.stderr).to match(%r{(.*group '?newgrp_1'? does not exist.*|.*Unknown group `?newgrp_1'?.*)})
+ end
+
+ expect(user('grp_flse')).not_to exist
+ expect(user('grp_flse')).not_to belong_to_group 'new_group_1'
+ end
+ end
+
+ describe 'group set to true creates group' do
+ it 'creates group' do
+ apply_manifest(pp_create_group_true, catch_failures: true)
+
+ expect(user('grp_true')).to exist
+ expect(user('grp_true')).to belong_to_group 'newgrp_2'
+ end
+ end
+
+ # Solaris does not offer a means of testing the password
+ describe 'ignore password if ignore set to true', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group, empty password, ignore true, ignores password' do
+ apply_manifest(pp_ignore_user_first_run, catch_failures: true)
+ apply_manifest(pp_ignore_user_second_run, catch_failures: true)
+
+ expect(user('ignore_user')).to exist
+ expect(user('ignore_user')).to contain_password 'foo'
+ end
+ end
+
+ # Solaris does not offer a means of testing the password
+ describe 'do not ignore password if ignore set to false', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group, empty password, ignore false, should not ignore password' do
+ apply_manifest(pp_no_ignore_user_first_run, catch_failures: true)
+ apply_manifest(pp_no_ignore_user_second_run, catch_failures: true)
+
+ expect(user('no_ignore_user')).to exist
+ expect(user('no_ignore_user')).to contain_password ''
+ end
+ end
+
+ describe 'do not ignore password if set and ignore set to true', unless: os[:family] == 'solaris' do
+ it 'creates group of matching names, assigns non-matching group, specify password, ignore, should not ignore password' do
+ apply_manifest(pp_specd_user_first_run, catch_failures: true)
+ apply_manifest(pp_specd_user_second_run, catch_failures: true)
+
+ expect(user('specd_user')).to exist
+ expect(user('specd_user')).to contain_password 'bar'
+ end
+ end
+
+ describe 'allow homedir archival before user deletion' do
+ it 'allows creating one user before deleting another' do
+ apply_manifest(pp_archive_homedir_before_user_deletion, catch_failures: true)
+
+ expect(user('archiver')).to exist
+ expect(user('specd_user')).not_to exist
+ expect(file('/home/specd_user')).not_to exist
+ end
+ end
+
+ describe 'create duplicate users with same uid' do
+ it 'runs with no errors' do
+ apply_manifest(pp_user_with_duplicate_uid, catch_failures: true)
+
+ expect(user('duplicate_user1')).to exist
+ expect(user('duplicate_user1')).to have_uid 1234
+
+ expect(user('duplicate_user2')).to exist
+ expect(user('duplicate_user2')).to have_uid 1234
+ end
+ end
+ describe 'allow password to be a Sentitive type' do
+ it 'runs with no errors' do
+ apply_manifest(pp_user_with_sensitive_password, catch_failures: true)
+
+ expect(user('sensitive_user')).to exist
+ expect(user('sensitive_user')).to contain_password 'bar'
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/default_facts.yml b/modules/utilities/unix/system/accounts_newer/accounts/spec/default_facts.yml
new file mode 100644
index 000000000..f777abfc9
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/default_facts.yml
@@ -0,0 +1,8 @@
+# Use default_module_facts.yml for module specific facts.
+#
+# Facts specified here will override the values provided by rspec-puppet-facts.
+---
+ipaddress: "172.16.254.254"
+ipaddress6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA"
+is_pe: false
+macaddress: "AA:AA:AA:AA:AA:AA"
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/defines/accounts_user_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/defines/accounts_user_spec.rb
new file mode 100644
index 000000000..cea4a2d4d
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/defines/accounts_user_spec.rb
@@ -0,0 +1,323 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'accounts::user' do
+ on_supported_os.each do |os, facts|
+ context "on #{os}" do
+ let(:facts) { facts }
+ let(:user_vars) do
+ case facts[:os]['family']
+ when 'Debian'
+ { dan_home: '/home/dan',
+ locked_shell: '/usr/sbin/nologin',
+ root_home: '/root' }
+ when 'Solaris'
+ { dan_home: '/export/home/dan',
+ locked_shell: '/usr/bin/false',
+ root_home: '/' }
+ else
+ { dan_home: '/home/dan',
+ locked_shell: '/sbin/nologin',
+ root_home: '/root' }
+ end
+ end
+
+ context "for user dan on #{facts[:os]['family']}" do
+ let(:title) { 'dan' }
+
+ describe 'expected defaults' do
+ let(:params) { {} }
+
+ it do
+ is_expected.to contain_user(title).with('shell' => '/bin/bash')
+ is_expected.to contain_user(title).with('home' => user_vars[:dan_home])
+ is_expected.to contain_user(title).with('ensure' => 'present')
+ is_expected.to contain_user(title).with('comment' => title)
+ is_expected.to contain_user(title).with('gid' => title)
+ is_expected.to contain_user(title).with('groups' => [])
+ is_expected.to contain_user(title).with('allowdupe' => false)
+ is_expected.to contain_user(title).with('managehome' => true)
+ end
+ it do
+ is_expected.to contain_group(title).with('ensure' => 'present')
+ is_expected.to contain_group(title).with('gid' => nil)
+ end
+ end
+
+ describe 'when setting user parameters' do
+ let(:params) do
+ {
+ ensure: 'present',
+ allowdupe: true,
+ comment: 'comment',
+ expiry: '2018-06-22',
+ gid: 456,
+ group: 'dan',
+ groups: ['admin'],
+ home: '/var/home/dan',
+ home_mode: '0755',
+ membership: 'inclusive',
+ password: 'foo',
+ password_max_age: 60,
+ shell: '/bin/csh',
+ sshkey_owner: 'dan',
+ sshkeys: ['ssh-rsa AAAAB3Nza...LiPk== dan@example1.net',
+ 'permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss AAAAB5...21S== dan key2',
+ 'command="/bin/echo Hello World",from="myhost.exapmle.com,192.168.1.1" ecdsa-sha2-nistp521 test_key vagrant2'],
+ uid: 123,
+ }
+ end
+
+ [:ensure, :allowdupe, :comment, :expiry, :groups, :home,
+ :membership, :password, :password_max_age].each do |param|
+ it { is_expected.to contain_user(title).with(param.to_s => params[param]) }
+ end
+ it do
+ is_expected.to contain_user(title).with('gid' => params[:group])
+ is_expected.to contain_group(params[:group]).with('ensure' => params[:ensure],
+ 'gid' => params[:gid])
+ end
+ it { is_expected.to contain_group(params[:group]).that_comes_before("User[#{title}]") }
+ it do
+ is_expected.to contain_accounts__home_dir(params[:home]).with('user' => title,
+ 'mode' => params[:home_mode])
+ end
+ it { is_expected.to contain_accounts__key_management("#{title}_key_management").with('sshkeys' => params[:sshkeys]) }
+ it { is_expected.to contain_ssh_authorized_key("#{params[:sshkey_owner]}_ssh-rsa_dan@example1.net_1e44b207704970cf4acb3470331b0e5c") }
+ it { is_expected.to contain_ssh_authorized_key("#{params[:sshkey_owner]}_ssh-dss_dan key2_6e9b8958712502a8b31e1c283b6e6fce") }
+ it { is_expected.to contain_ssh_authorized_key("#{params[:sshkey_owner]}_ecdsa-sha2-nistp521_vagrant2_8c32d1183251df9828f929b935ae0419") }
+ it { is_expected.to contain_file("#{params[:home]}/.ssh") }
+ end
+
+ describe 'when locking users' do
+ let(:params) { { 'locked' => true } }
+
+ it { is_expected.to contain_user(title).with('shell' => user_vars[:locked_shell]) }
+ end
+
+ describe 'when setting custom sshkey location' do
+ let(:params) { { sshkey_custom_path: '/var/lib/ssh/dan/custom_key_file' } }
+
+ it { is_expected.to contain_file(params[:sshkey_custom_path]) }
+ end
+
+ describe 'when setting sshkey mode on custom sshkey location' do
+ let(:params) do
+ { sshkey_mode: '0440',
+ sshkey_custom_path: '/var/lib/ssh/dan/custom_key_file' }
+ end
+
+ it { is_expected.to contain_file(params[:sshkey_custom_path]).with(mode: '0440') }
+ end
+
+ describe 'with create_group set to false' do
+ let(:params) do
+ { group: 'foo',
+ create_group: false,
+ ensure: 'present' }
+ end
+
+ it { is_expected.not_to contain_group(params[:group]) }
+ end
+
+ describe 'with create_group set to true' do
+ let(:params) do
+ { group: 'foo',
+ create_group: true,
+ ensure: 'present' }
+ end
+
+ it { is_expected.to contain_group(params[:group]) }
+ end
+
+ describe 'with forcelocal set to false' do
+ let(:params) do
+ { forcelocal: false }
+ end
+
+ it { is_expected.to contain_user(title).with('forcelocal' => params[:forcelocal]) }
+ it { is_expected.to contain_group(title).with('forcelocal' => params[:forcelocal]) }
+ end
+
+ describe 'with forcelocal set to true' do
+ let(:params) do
+ { forcelocal: true }
+ end
+
+ it { is_expected.to contain_user(title).with('forcelocal' => params[:forcelocal]) }
+ it { is_expected.to contain_group(title).with('forcelocal' => params[:forcelocal]) }
+ end
+
+ describe 'when empty password ignored' do
+ let(:params) do
+ { ignore_password_if_empty: true,
+ password: '' }
+ end
+
+ it { is_expected.to contain_user(title).without_password }
+ end
+
+ describe 'when empty password not ignored explicitly' do
+ let(:params) do
+ { ignore_password_if_empty: false,
+ password: '' }
+ end
+
+ it { is_expected.to contain_user(title).with('password' => params[:password]) }
+ end
+
+ describe 'when empty password not ignored by default' do
+ let(:params) { { password: '' } }
+
+ it { is_expected.to contain_user(title).with('password' => params[:password]) }
+ end
+
+ describe 'when non-empty password not ignored' do
+ let(:params) do
+ { ignore_password_if_empty: false,
+ password: 'foo' }
+ end
+
+ it { is_expected.to contain_user(title).with('password' => params[:password]) }
+ end
+
+ describe 'when non-empty password ignored if empty' do
+ let(:params) do
+ { ignore_password_if_empty: true,
+ password: 'foo' }
+ end
+
+ it { is_expected.to contain_user(title).with('password' => params[:password]) }
+ end
+
+ describe 'when setting password iterations and salt' do
+ let(:params) do
+ { iterations: 5,
+ salt: 'bar' }
+ end
+
+ it { is_expected.to contain_user(title).with('iterations' => params[:iterations]) }
+ it { is_expected.to contain_user(title).with('salt' => params[:salt]) }
+ end
+
+ describe 'when using a sensitive password' do
+ let(:params) do
+ { password: RSpec::Puppet::RawString.new("Sensitive('foo')") }
+ end
+
+ it { is_expected.to contain_user(title).with('password' => sensitive('foo')) }
+ end
+
+ describe 'when supplying resource defaults' do
+ let(:params) { {} }
+ let(:pre_condition) { "Accounts::User{ shell => '/bin/zsh' }" }
+
+ it { is_expected.to contain_user(title).with('shell' => '/bin/zsh') }
+ end
+
+ describe 'when explicit parameters override defaults' do
+ let(:params) { { 'shell' => '/bin/csh' } }
+ let(:pre_condition) { "Accounts::User{ shell => '/bin/zsh' }" }
+
+ it { is_expected.to contain_user(title).with('shell' => '/bin/csh') }
+ end
+
+ describe 'when locked overrides defaults and user params' do
+ let(:params) do
+ { 'locked' => true,
+ 'shell' => '/bin/csh' }
+ end
+ let(:pre_condition) { "Accounts::User{ shell => '/bin/zsh' }" }
+
+ it { is_expected.to contain_user(title).with('shell' => user_vars[:locked_shell]) }
+ end
+
+ context 'when setting the user to absent' do
+ # when deleting users the home dir is a File resource instead of a accounts::home_dir
+ let(:contain_home_dir) { contain_file(params[:home]) }
+
+ describe 'with default sshkey path' do
+ let(:params) do
+ { ensure: 'absent',
+ purge_user_home: true }
+ end
+
+ it { is_expected.to contain_user(title).with('ensure' => params[:ensure]) }
+ it { is_expected.to contain_user(title).that_comes_before("Group[#{title}]") }
+ it { is_expected.to contain_group(title).with('ensure' => params[:ensure]) }
+ it { is_expected.not_to contain_accounts__home_dir(user_vars[:dan_home]) }
+ end
+
+ describe 'with custom sshkey location' do
+ let(:params) do
+ { ensure: 'absent',
+ purge_user_home: true,
+ sshkey_custom_path: '/var/lib/ssh/dan/custom_key_file' }
+ end
+
+ it { is_expected.to contain_file(params[:sshkey_custom_path]).with('ensure' => params[:ensure]).that_comes_before("User[#{title}]") }
+ end
+
+ describe 'with purge_user_home off' do
+ let(:params) do
+ { ensure: 'absent',
+ purge_user_home: false }
+ end
+
+ it { is_expected.to contain_user(title).with('ensure' => params[:ensure]) }
+ it { is_expected.to contain_user(title).with('managehome' => params[:purge_user_home]) }
+ it { is_expected.not_to contain_accounts__home_dir(user_vars[:dan_home]) }
+ it { is_expected.not_to contain_file("#{user_vars[:dan_home]}/.ssh") }
+ end
+ end
+ end
+
+ context 'for user root' do
+ let(:title) { 'root' }
+ let(:params) { {} }
+
+ describe 'expected defaults' do
+ it { is_expected.to contain_user(title).with_home(user_vars[:root_home]) }
+ end
+ end
+
+ context 'invalid parameter values' do
+ let(:title) { 'dan' }
+
+ describe "only accepts 'absent' and 'present' for ensure" do
+ let(:params) { { ensure: 'invalid' } }
+
+ it { is_expected.to raise_error Puppet::Error }
+ end
+ [:home, :shell].each do |param|
+ describe "should fail if #{param} does not start with '/'" do
+ let(:params) { { param => 'no_leading_slash' } }
+
+ it { is_expected.to raise_error Puppet::Error }
+ end
+ end
+ describe 'does not accept non-date values for expiry' do
+ let(:params) { { expiry: 'notadate' } }
+
+ it { is_expected.to raise_error Puppet::Error }
+ end
+ [:gid, :uid].each do |param|
+ describe "fails if #{param} is not composed of digits" do
+ let(:params) { { param => 'name' } }
+
+ it { is_expected.to raise_error Puppet::Error }
+ end
+ end
+ [:allowdupe, :expiry, :locked, :managehome,
+ :managevim, :purge_user_home].each do |param|
+ describe "fails if #{param} is not a boolean" do
+ let(:params) { { param => 'true' } }
+
+ it { is_expected.to raise_error Puppet::Error }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_authorized_keys_line_parser_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_authorized_keys_line_parser_spec.rb
new file mode 100644
index 000000000..834ae0609
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_authorized_keys_line_parser_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'accounts_ssh_authorized_keys_line_parser' do
+ it {
+ is_expected.not_to eq(nil)
+ }
+ it {
+ is_expected.to run.with_params('').and_raise_error(ArgumentError, %r{Wrong Keyline format!})
+ }
+ it {
+ is_expected.to run.with_params('options unknown-keytype key comment').and_raise_error(ArgumentError, %r{Wrong Keyline format!})
+ }
+ it {
+ is_expected.to run.with_params('ssh-xyz key name with spaces').and_return( \
+ ['', 'ssh-xyz', 'key', 'name with spaces'],
+ )
+ }
+ it {
+ is_expected.to run.with_params('"options with arguments",moreoptions,"moreoptions with arguments" ecdsa-xyz key name with spaces').and_return( \
+ ['"options with arguments",moreoptions,"moreoptions with arguments"', 'ecdsa-xyz', 'key', 'name with spaces'],
+ )
+ }
+ it {
+ is_expected.to run.with_params('tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== jane@example.net').and_return( \
+ ['tunnel="0",command="sh /etc/netstart tun0"', 'ssh-rsa', 'AAAA...==', 'jane@example.net'],
+ )
+ }
+ it {
+ # rubocop:disable Layout/LineLength
+ is_expected.to run.with_params('command="rsync --server --sender -vlHogtpr --numeric-ids . /",from="192.168.1.1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ecdsa-sha2-nistp384 AAAA...= rsync backup').and_return( \
+ ['command="rsync --server --sender -vlHogtpr --numeric-ids . /",from="192.168.1.1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding', 'ecdsa-sha2-nistp384', 'AAAA...=', 'rsync backup'],
+ )
+ # rubocop:enable Layout/LineLength
+ }
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_options_parser_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_options_parser_spec.rb
new file mode 100644
index 000000000..1d9373278
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/functions/accounts_ssh_options_parser_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'accounts_ssh_options_parser' do
+ it { is_expected.not_to eq(nil) }
+ it { is_expected.to run.with_params('').and_return([]) }
+ it { is_expected.to run.with_params('"').and_raise_error(ArgumentError, %r{Unmatched double quote}) }
+ it { is_expected.to run.with_params('tunnel="0"').and_return(['tunnel="0"']) }
+ it { is_expected.to run.with_params('restrict,tunnel="0",command="sh /etc/netstart tun0"').and_return(['restrict', 'tunnel="0"', 'command="sh /etc/netstart tun0"']) }
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper.rb
new file mode 100644
index 000000000..07db73426
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+RSpec.configure do |c|
+ c.mock_with :rspec
+end
+
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+
+require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb'))
+
+include RspecPuppetFacts
+
+default_facts = {
+ puppetversion: Puppet.version,
+ facterversion: Facter.version,
+}
+
+default_fact_files = [
+ File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')),
+ File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')),
+]
+
+default_fact_files.each do |f|
+ next unless File.exist?(f) && File.readable?(f) && File.size?(f)
+
+ begin
+ default_facts.merge!(YAML.safe_load(File.read(f), [], [], true))
+ rescue => e
+ RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}"
+ end
+end
+
+# read default_facts and merge them over what is provided by facterdb
+default_facts.each do |fact, value|
+ add_custom_fact fact, value
+end
+
+RSpec.configure do |c|
+ c.default_facts = default_facts
+ c.before :each do
+ # set to strictest setting for testing
+ # by default Puppet runs at warning level
+ Puppet.settings[:strict] = :warning
+ Puppet.settings[:strict_variables] = true
+ end
+ c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT']
+ c.after(:suite) do
+ RSpec::Puppet::Coverage.report!(0)
+ end
+
+ # Filter backtrace noise
+ backtrace_exclusion_patterns = [
+ %r{spec_helper},
+ %r{gems},
+ ]
+
+ if c.respond_to?(:backtrace_exclusion_patterns)
+ c.backtrace_exclusion_patterns = backtrace_exclusion_patterns
+ elsif c.respond_to?(:backtrace_clean_patterns)
+ c.backtrace_clean_patterns = backtrace_exclusion_patterns
+ end
+end
+
+# Ensures that a module is defined
+# @param module_name Name of the module
+def ensure_module_defined(module_name)
+ module_name.split('::').reduce(Object) do |last_module, next_module|
+ last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false)
+ last_module.const_get(next_module, false)
+ end
+end
+
+# 'spec_overrides' from sync.yml will appear below this line
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance.rb
new file mode 100644
index 000000000..4ac8d7e0f
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+require 'puppet_litmus'
+require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb'))
+
+PuppetLitmus.configure!
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance_local.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance_local.rb
new file mode 100644
index 000000000..dc76ae01b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_acceptance_local.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'bolt_spec/run'
+require 'puppet_litmus/inventory_manipulation'
+
+UNSUPPORTED_PLATFORMS = ['windows', 'darwin'].freeze
+
+# rubocop:disable all
+#####################################################################################
+# Partially copied from simp/rubygem-simp-beaker-helpers/lib/simp/beaker_helpers.rb #
+# Original copyright therefrom applies. #
+#####################################################################################
+
+# A shim to stand in for the now deprecated hiera_datadir function
+#
+# Note: This may not work if you've shoved data somewhere that is not the
+# default and/or are manipulating the default hiera.yaml.
+#
+# @returns [String] Path to the Hieradata directory on the target system
+def hiera_datadir
+ # This output lets us know where Hiera is configured to look on the system
+ puppet_lookup_info = run_shell('puppet lookup --explain test__simp__test').stdout.strip.lines
+ puppet_config_check = run_shell('puppet agent --configprint manifest').stdout
+
+ if puppet_config_check.nil? || puppet_config_check.empty?
+ fail("No output returned from `puppet config print manifest`")
+ end
+
+ puppet_env_path = File.dirname(puppet_config_check)
+
+ # We'll just take the first match since Hiera will find things there
+ puppet_lookup_info = puppet_lookup_info.grep(/Path "/).grep(Regexp.new(puppet_env_path))
+
+ # Grep always returns an Array
+ if puppet_lookup_info.empty?
+ fail("Could not determine hiera data directory under #{puppet_env_path}")
+ end
+
+ # Snag the actual path without the extra bits
+ puppet_lookup_info = puppet_lookup_info.first.strip.split('"').last
+
+ # Make the parent directories exist
+ run_shell("mkdir -p #{File.dirname(puppet_lookup_info)}", acceptable_exit_codes: [0])
+
+ # We just want the data directory name
+ datadir_name = puppet_lookup_info.split(puppet_env_path).last
+
+ # Grab the file separator to add back later
+ file_sep = datadir_name[0]
+
+ # Snag the first entry (this is the data directory)
+ datadir_name = datadir_name.split(file_sep)[1]
+
+ # Constitute the full path to the data directory
+ datadir_path = puppet_env_path + file_sep + datadir_name
+
+ # Return the path to the data directory
+ return datadir_path
+end
+
+# Write the provided data structure to Hiera's :datadir and configure Hiera to
+# use that data exclusively.
+#
+# @note This is authoritative. It manages both Hiera data and configuration,
+# so it may not be used with other Hiera data sources.
+#
+# @param hieradata [Hash, String] The full hiera data structure to write to
+# the system.
+#
+# @return [Nil]
+#
+def set_hieradata(hieradata)
+ @temp_hieradata_dirs ||= []
+ data_dir = Dir.mktmpdir('hieradata')
+ @temp_hieradata_dirs << data_dir
+
+ fh = File.open(File.join(data_dir, 'common.yaml'), 'w')
+ if hieradata.is_a?(String)
+ fh.puts(hieradata)
+ else
+ fh.puts(hieradata.to_yaml)
+ end
+ fh.close
+
+ run_shell("mkdir -p #{File.dirname(data_dir)}", acceptable_exit_codes: [0])
+ result = upload_file(File.join(data_dir, 'common.yaml'), File.join(@hiera_datadir, 'common.yaml'), ENV['TARGET_HOST'], options: {}, config: nil, inventory: inventory_hash_from_inventory_file)
+ raise "error uploading hiera file to #{ENV['TARGET_HOST']}" if result[0]["status"] !~ %r{success}
+end
+
+# Clean up all temporary hiera data files.
+#
+# Meant to be called from after(:all)
+def clear_temp_hieradata
+ if @temp_hieradata_dirs && !@temp_hieradata_dirs.empty?
+ @temp_hieradata_dirs.each do |data_dir|
+ if File.exists?(data_dir)
+ FileUtils.rm_r(data_dir)
+ end
+ end
+ end
+end
+
+RSpec.configure do |c|
+ c.before(:all) do
+ @temp_hieradata_dirs = @temp_hieradata_dirs || []
+ @hiera_datadir = hiera_datadir
+ end
+
+ c.after(:all) do
+ clear_temp_hieradata
+ end
+
+ c.formatter = :documentation
+end
+
+###########################################################################
+# End copying simp/rubygem-simp-beaker-helpers/lib/simp/beaker_helpers.rb #
+###########################################################################
+# rubocop:enable all
+
+RSpec::Matchers.define :contain_password do |password|
+ match do |user|
+ if password == user.encrypted_password
+ return true
+ end
+ end
+ false
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_local.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_local.rb
new file mode 100644
index 000000000..ce4d0623f
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/spec_helper_local.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+if ENV['COVERAGE'] == 'yes'
+ require 'simplecov'
+ require 'simplecov-console'
+ require 'codecov'
+
+ SimpleCov.formatters = [
+ SimpleCov::Formatter::HTMLFormatter,
+ SimpleCov::Formatter::Console,
+ SimpleCov::Formatter::Codecov,
+ ]
+ SimpleCov.start do
+ track_files 'lib/**/*.rb'
+
+ add_filter '/spec'
+
+ # do not track vendored files
+ add_filter '/vendor'
+ add_filter '/.vendor'
+
+ # do not track gitignored files
+ # this adds about 4 seconds to the coverage check
+ # this could definitely be optimized
+ add_filter do |f|
+ # system returns true if exit status is 0, which with git-check-ignore means file is ignored
+ system("git check-ignore --quiet #{f.filename}")
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_hash_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_hash_spec.rb
new file mode 100644
index 000000000..7b907b464
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_hash_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::Group::Hash' do
+ describe 'Valid group hash values' do
+ [
+ { 'oldusers' => { 'ensure' => 'absent' } },
+ { 'sudoers' => { 'system' => true } },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid group hash values' do
+ [
+ { '$$' => {} },
+ { '_a' => { 'ensure' => false } },
+ { '_b' => { 'allowdupe' => 'soitenly!' } },
+ { '_c' => { 'auth_membership' => [] } },
+ { '_d' => { 'forcelocal' => {} } },
+ { '_e' => { 'gid' => 'nine' } },
+ { '_f' => { 'members' => [-1] } },
+ { '_g' => { 'provider' => nil } },
+ { '_h' => { 'system' => 'POSIX' } },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_provider_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_provider_spec.rb
new file mode 100644
index 000000000..cc9b8e0bf
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_provider_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::Group::Provider' do
+ describe 'Valid group provider values' do
+ [
+ 'aix',
+ 'directoryservice',
+ 'groupadd',
+ 'ldap',
+ 'pw',
+ 'windows_adsi',
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid group provider values' do
+ [
+ 0,
+ false,
+ 'GroupAdd',
+ '',
+ {},
+ [],
+ nil,
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_resource_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_resource_spec.rb
new file mode 100644
index 000000000..b19a2e800
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/group_resource_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::Group::Resource' do
+ describe 'Valid group resource values' do
+ [
+ {},
+ { 'ensure' => 'absent' },
+ { 'allowdupe' => false },
+ { 'auth_membership' => true },
+ { 'forcelocal' => false },
+ { 'gid' => 999 },
+ { 'members' => ['root'] },
+ { 'name' => 'root' },
+ { 'provider' => 'pw' },
+ { 'system' => false },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid group resource values' do
+ [
+ { 'bogus' => true },
+ { 'ensure' => false },
+ { 'allowdupe' => 'soitenly!' },
+ { 'auth_membership' => 'no' },
+ { 'forcelocal' => -1 },
+ { 'gid' => 'nine' },
+ { 'members' => [-1] },
+ { 'name' => '$invalid' },
+ { 'provider' => 'Custom' },
+ { 'system' => 'Linux' },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_expiry_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_expiry_spec.rb
new file mode 100644
index 000000000..0be37f058
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_expiry_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Expiry' do
+ describe 'Valid user expiry values' do
+ [
+ 'absent',
+ '1901-01-01',
+ '1992-02-04',
+ '2183-03-06',
+ '3274-04-09',
+ '3365-05-12',
+ '4456-06-15',
+ '5547-07-17',
+ '6638-08-20',
+ '7729-09-22',
+ '8820-10-25',
+ '9911-11-27',
+ '9999-12-31',
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user expiry values' do
+ [
+ 'present',
+ '0001-01-01',
+ '0010-01-01',
+ '0100-01-01',
+ '1000-01-01',
+ '1899-01-01',
+ '1900-00-01',
+ '2000-13-01',
+ '2100-01-00',
+ '2100-01-00',
+ '2200-01-32',
+ '....-..-..',
+ '1999.01.01',
+ '--',
+ '',
+ {},
+ [],
+ nil,
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_hash_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_hash_spec.rb
new file mode 100644
index 000000000..e927e7c36
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_hash_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Hash' do
+ describe 'Valid user hash values' do
+ [
+ { 'jdoe' => { 'comment' => 'Jane Doe' } },
+ { 'rroe' => { 'forward_content' => 'richard.roe@example.com' } },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user hash values' do
+ [
+ { '$$' => {} },
+ { '_a' => { 'ensure' => false } },
+ { '_b' => { 'allowdupe' => 'soitenly!' } },
+ { '_c' => { 'bash_profile_content' => false } },
+ { '_d' => { 'bash_profile_source' => nil } },
+ { '_e' => { 'bashrc_content' => 1 } },
+ { '_f' => { 'bashrc_source' => [] } },
+ { '_g' => { 'comment' => {} } },
+ { '_h' => { 'create_group' => 'users' } },
+ { '_i' => { 'expiry' => 'never' } },
+ { '_j' => { 'forcelocal' => -1 } },
+ { '_k' => { 'forward_content' => [] } },
+ { '_l' => { 'forward_source' => {} } },
+ { '_m' => { 'gid' => 'nine' } },
+ { '_n' => { 'group' => 0 } },
+ { '_o' => { 'groups' => [-1] } },
+ { '_p' => { 'name' => '$invalid' } },
+ { '_q' => { 'home' => 'C:\\' } },
+ { '_r' => { 'home_mode' => '999' } },
+ { '_s' => { 'ignore_password_if_empty' => 'always' } },
+ { '_t' => { 'iterations' => 0 } },
+ { '_u' => { 'locked' => [] } },
+ { '_v' => { 'managehome' => {} } },
+ { '_w' => { 'managevim' => 'vim' } },
+ { '_x' => { 'membership' => 'exclusive' } },
+ { '_y' => { 'password' => 123 } },
+ { '_z' => { 'purge_sshkeys' => 'no way' } },
+ { '_0' => { 'purge_user_home' => [] } },
+ { '_1' => { 'salt' => {} } },
+ { '_2' => { 'shell' => 'bash' } },
+ { '_3' => { 'sshkey_custom_path' => '../../etc' } },
+ { '_4' => { 'sshkey_owner' => [] } },
+ { '_5' => { 'sshkeys' => {} } },
+ { '_6' => { 'system' => 'Linux' } },
+ { '_7' => { 'uid' => -1 } },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_iterations_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_iterations_spec.rb
new file mode 100644
index 000000000..f56de44ac
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_iterations_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Iterations' do
+ describe 'Valid user iterations values' do
+ [
+ 1,
+ 23,
+ 456,
+ 7890,
+ '1',
+ '23',
+ '456',
+ '7890',
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user iterations values' do
+ [
+ 0,
+ -1,
+ '02',
+ '-3',
+ 'four',
+ '',
+ {},
+ [],
+ nil,
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_name_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_name_spec.rb
new file mode 100644
index 000000000..b2b47b97b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_name_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Name' do
+ describe 'Valid user name values' do
+ [
+ '1-bad-dude', # Depending on the distribution, this might be an issue, however should be left to the distributions
+ 'a',
+ '_', # Technically allowed but probably shouldn't be.
+ 'bravo',
+ 'charlie-99.Delta', # Can contain dashes, digits, dots and capitals.
+ 'ecHo123',
+ 'foxtrot$', # Can end in a dollar-sign
+ '_golf_321_$',
+ 'supercalifragilisticexpialidocio', # 32 characters
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user name values' do
+ [
+ '.hidden', # Cannot begin with a period.
+ '$money', # Cannot begin with a dollar-sign.
+ '-kilroy_was_here-', # Cannot begin with a dash.
+ 'more-$-and-cents', # Cannot have a dollar-sign in the middle.
+ 'fred.', # Cannot end in a period.
+ 'supercalifragilisticexpialiadocious', # Too long: must be 1-32 chars.
+ '', # Cannot be empty.
+ 5, # Or a non-string.
+ {},
+ [],
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_resource_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_resource_spec.rb
new file mode 100644
index 000000000..0dd71c56d
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_resource_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Resource' do
+ describe 'Valid user resource values' do
+ [
+ {},
+ { 'ensure' => 'absent' },
+ { 'allowdupe' => false },
+ { 'bash_profile_content' => 'export foo=bar' },
+ { 'bash_profile_source' => '/etc/defaults/bash_profile' },
+ { 'bashrc_content' => 'alias bar=foo' },
+ { 'bashrc_source' => '/etc/profile' },
+ { 'comment' => 'Joe User' },
+ { 'create_group' => true },
+ { 'expiry' => 'absent' },
+ { 'forcelocal' => false },
+ { 'forward_content' => 'root@localhost' },
+ { 'forward_source' => '/root/.forward' },
+ { 'gid' => 0 },
+ { 'group' => 'root' },
+ { 'groups' => [] },
+ { 'name' => 'root' },
+ { 'home' => '/root' },
+ { 'home_mode' => '700' },
+ { 'ignore_password_if_empty' => true },
+ { 'iterations' => 10_000 },
+ { 'locked' => false },
+ { 'managehome' => true },
+ { 'managevim' => false },
+ { 'membership' => 'inclusive' },
+ { 'name' => 'root' },
+ { 'password' => 'password123' },
+ { 'purge_sshkeys' => true },
+ { 'purge_user_home' => false },
+ { 'salt' => 'zyzzyx' },
+ { 'shell' => '/bin/false' },
+ { 'sshkey_custom_path' => '/etc/ssh/local_keys/root' },
+ { 'sshkey_owner' => 'root' },
+ { 'sshkeys' => [] },
+ { 'system' => false },
+ { 'uid' => 0 },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user resource values' do
+ [
+ { 'bogus' => true },
+ { 'ensure' => false },
+ { 'allowdupe' => 'soitenly!' },
+ { 'bash_profile_content' => false },
+ { 'bash_profile_source' => nil },
+ { 'bashrc_content' => 1 },
+ { 'bashrc_source' => [] },
+ { 'comment' => {} },
+ { 'create_group' => 'groupname' },
+ { 'expiry' => 'never' },
+ { 'forcelocal' => -1 },
+ { 'forward_content' => ['not', 'a', 'string'] },
+ { 'forward_source' => { '*' => 'root@localhost' } },
+ { 'gid' => 'nine' },
+ { 'group' => 0 },
+ { 'groups' => [-1] },
+ { 'name' => '$invalid' },
+ { 'home' => 'C:\Users\Administrator' },
+ { 'home_mode' => '999' },
+ { 'ignore_password_if_empty' => 'always' },
+ { 'iterations' => 0 },
+ { 'locked' => [] },
+ { 'managehome' => {} },
+ { 'managevim' => 'vim' },
+ { 'membership' => 'exclusive' },
+ { 'password' => 123 },
+ { 'purge_sshkeys' => 'no way' },
+ { 'purge_user_home' => [] },
+ { 'salt' => {} },
+ { 'shell' => 'bash' },
+ { 'sshkey_custom_path' => '../../etc/ssh/key' },
+ { 'sshkey_owner' => [] },
+ { 'sshkeys' => {} },
+ { 'system' => 'Linux' },
+ { 'uid' => -1 },
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_uid_spec.rb b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_uid_spec.rb
new file mode 100644
index 000000000..97299dbc3
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/spec/type_aliases/user_uid_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Accounts::User::Uid' do
+ describe 'Valid user uid values' do
+ [
+ 0,
+ 12,
+ 345,
+ 6789,
+ 78_901,
+ 890_123,
+ 999_999_999,
+ '1000000001',
+ '2000000002',
+ '3999999999',
+ '4199999999',
+ '4289999999',
+ '4293999999',
+ '4294899999',
+ '4294966999',
+ '4294967199',
+ '4294967289',
+ '4294967295',
+ 2**32 - 1,
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.to allow_value(value) }
+ end
+ end
+ end
+
+ describe 'Invalid user uid values' do
+ [
+ -1,
+ '-1',
+ 2**32,
+ '4294967296',
+ '007',
+ '',
+ {},
+ [],
+ nil,
+ ].each do |value|
+ describe value.inspect do
+ it { is_expected.not_to allow_value(value) }
+ end
+ end
+ end
+end
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/group/hash.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/group/hash.pp
new file mode 100644
index 000000000..0f961260d
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/group/hash.pp
@@ -0,0 +1,7 @@
+# Group resoureces hash.
+# @summary A hash of group resources, keyed by group name.
+# Passed as the second parameter of the ensure_resources function.
+#
+type Accounts::Group::Hash = Hash[
+ Accounts::User::Name, Accounts::Group::Resource
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/group/provider.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/group/provider.pp
new file mode 100644
index 000000000..998a6ddb7
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/group/provider.pp
@@ -0,0 +1,13 @@
+# Group provider.
+# @summary The specific backend to use for this group resource.
+# You will seldom need to specify this -- Puppet will usually discover the
+# appropriate provider for your platform.
+#
+type Accounts::Group::Provider = Enum[
+ 'aix',
+ 'directoryservice',
+ 'groupadd',
+ 'ldap',
+ 'pw',
+ 'windows_adsi'
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/group/resource.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/group/resource.pp
new file mode 100644
index 000000000..c65a81c87
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/group/resource.pp
@@ -0,0 +1,16 @@
+# Group attributes hash.
+# @summary A hash of group attributes.
+# Passed as the third parameter of the ensure_resources function.
+#
+type Accounts::Group::Resource = Struct[
+ { Optional[ensure] => Enum['absent', 'present'],
+ Optional[allowdupe] => Boolean,
+ Optional[auth_membership] => Boolean,
+ Optional[forcelocal] => Boolean,
+ Optional[gid] => Accounts::User::Uid,
+ Optional[members] => Array[Accounts::User::Name],
+ Optional[name] => Accounts::User::Name,
+ Optional[provider] => Accounts::Group::Provider,
+ Optional[system] => Boolean,
+ }
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/expiry.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/expiry.pp
new file mode 100644
index 000000000..1be7817fe
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/expiry.pp
@@ -0,0 +1,8 @@
+# Account expiration date.
+# @summary Account access will be denied after this date.
+# Either 'absent' or a YYYY-MM-DD datestring.
+#
+type Accounts::User::Expiry = Variant[
+ Enum['absent'],
+ Pattern[/\A(19|[2-9]\d)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])\z/]
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/hash.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/hash.pp
new file mode 100644
index 000000000..3326af82c
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/hash.pp
@@ -0,0 +1,7 @@
+# User resources hash.
+# @summary A hash of user resources, keyed by user name.
+# Passed as the second parameter of the ensure_resources function.
+#
+type Accounts::User::Hash = Hash[
+ Accounts::User::Name, Accounts::User::Resource
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/iterations.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/iterations.pp
new file mode 100644
index 000000000..11061cc4b
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/iterations.pp
@@ -0,0 +1,9 @@
+# Password hash iterations.
+# @summary Chained computation iterations for the PBKDF2 password hash.
+# This parameter is used in OS X, and is required for managing passwords
+# on OS X 10.8 and newer.
+#
+type Accounts::User::Iterations = Variant[
+ Integer[1,],
+ Pattern[/\A[1-9]\d*\z/],
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/name.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/name.pp
new file mode 100644
index 000000000..ac0577db7
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/name.pp
@@ -0,0 +1,11 @@
+# Account (user or group) name.
+# @summary Each user or group should have a unique alphanumeric name.
+# From useradd(8): It is usually recommended to only use usernames
+# that begin with a lower case letter or an underscore, followed by lower case
+# letters, digits, underscores, or dashes. They can end with a dollar sign.
+# Usernames may only be up to 32 characters long.
+#
+# Many installations also allow capitals or periods, for example to separate first and
+# last names.
+#
+type Accounts::User::Name = Pattern[/\A[a-zA-Z0-9_]([a-zA-Z.0-9_-]{0,30}[a-zA-Z0-9_$-])?\z/]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/passwordmaxage.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/passwordmaxage.pp
new file mode 100644
index 000000000..8ecb90d39
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/passwordmaxage.pp
@@ -0,0 +1,6 @@
+# Max password age.
+# @summary Maximum days between password changes.
+# On most systems, the default value of 99999 is about 274 years, which
+# effectively disables password aging.
+#
+type Accounts::User::PasswordMaxAge = Integer[1, 99999]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/resource.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/resource.pp
new file mode 100644
index 000000000..b26f6bc6f
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/resource.pp
@@ -0,0 +1,44 @@
+# User attributes hash.
+# @summary A hash of user attributes.
+# Passed as the third parameter of the ensure_resources function.
+#
+type Accounts::User::Resource = Struct[
+ { Optional[ensure] => Enum['absent','present'],
+ Optional[allowdupe] => Boolean,
+ Optional[bash_profile_content] => String,
+ Optional[bash_profile_source] => Stdlib::Filesource,
+ Optional[bashrc_content] => String,
+ Optional[bashrc_source] => Stdlib::Filesource,
+ Optional[comment] => String,
+ Optional[create_group] => Boolean,
+ Optional[expiry] => Accounts::User::Expiry,
+ Optional[forcelocal] => Boolean,
+ Optional[forward_content] => String,
+ Optional[forward_source] => Stdlib::Filesource,
+ Optional[gid] => Accounts::User::Uid,
+ Optional[group] => Accounts::User::Name,
+ Optional[groups] => Array[Accounts::User::Name],
+ Optional[name] => Accounts::User::Name,
+ Optional[home] => Stdlib::Unixpath,
+ Optional[home_mode] => Stdlib::Filemode,
+ Optional[ignore_password_if_empty] => Boolean,
+ Optional[iterations] => Accounts::User::Iterations,
+ Optional[locked] => Boolean,
+ Optional[managehome] => Boolean,
+ Optional[managevim] => Boolean,
+ Optional[membership] => Enum['inclusive','minimum'],
+ Optional[name] => Accounts::User::Name,
+ Optional[password] => String,
+ Optional[password_max_age] => Accounts::User::PasswordMaxAge,
+ Optional[purge_sshkeys] => Boolean,
+ Optional[purge_user_home] => Boolean,
+ Optional[salt] => String,
+ Optional[shell] => Stdlib::Unixpath,
+ Optional[sshkey_custom_path] => Stdlib::Unixpath,
+ Optional[sshkey_owner] => Accounts::User::Name,
+ Optional[sshkey_group] => Accounts::User::Name,
+ Optional[sshkeys] => Array[String],
+ Optional[system] => Boolean,
+ Optional[uid] => Accounts::User::Uid,
+ }
+]
diff --git a/modules/utilities/unix/system/accounts_newer/accounts/types/user/uid.pp b/modules/utilities/unix/system/accounts_newer/accounts/types/user/uid.pp
new file mode 100644
index 000000000..d89dd43fa
--- /dev/null
+++ b/modules/utilities/unix/system/accounts_newer/accounts/types/user/uid.pp
@@ -0,0 +1,20 @@
+# Numeric user ID.
+# @summary Each user on a system should have a unique numeric uid.
+# On most Unix systems, the highest uid is 2^32 - 1, or 4294967295.
+#
+type Accounts::User::Uid = Variant[
+ Integer[0,4294967295],
+ Pattern[/\A0\z/,
+ /\A[1-3]\d{0,9}\z/,
+ /\A[4-9]\d{0,8}\z/,
+ /\A4[0-1]\d{8}\z/,
+ /\A42[0-8]\d{7}\z/,
+ /\A429[0-3]\d{6}\z/,
+ /\A4294[0-8]\d{5}\z/,
+ /\A42949[0-5]\d{4}\z/,
+ /\A429496[0-6]\d{3}\z/,
+ /\A4294967[0-1]\d{2}\z/,
+ /\A42949672[0-8]\d\z/,
+ /\A429496729[0-5]\z/,
+ ]
+]
diff --git a/modules/utilities/unix/system/groups/secgen_metadata.xml b/modules/utilities/unix/system/groups/secgen_metadata.xml
index 393e8450e..38bf6ca73 100644
--- a/modules/utilities/unix/system/groups/secgen_metadata.xml
+++ b/modules/utilities/unix/system/groups/secgen_metadata.xml
@@ -15,7 +15,7 @@
groups
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/utilities/unix/system/hosts/secgen_metadata.xml b/modules/utilities/unix/system/hosts/secgen_metadata.xml
index 66bbb0933..23e84a14b 100644
--- a/modules/utilities/unix/system/hosts/secgen_metadata.xml
+++ b/modules/utilities/unix/system/hosts/secgen_metadata.xml
@@ -19,7 +19,7 @@
hostnames
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/utilities/unix/system/parameterised_accounts/secgen_metadata.xml b/modules/utilities/unix/system/parameterised_accounts/secgen_metadata.xml
index 703957bba..8cd978332 100644
--- a/modules/utilities/unix/system/parameterised_accounts/secgen_metadata.xml
+++ b/modules/utilities/unix/system/parameterised_accounts/secgen_metadata.xml
@@ -20,7 +20,7 @@
accounts
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/misc/hidden_file/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/misc/hidden_file/secgen_metadata.xml
index 9b331b25e..1c4ad2226 100644
--- a/modules/vulnerabilities/unix/ctf/misc/hidden_file/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/misc/hidden_file/secgen_metadata.xml
@@ -64,7 +64,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/programming/math_challenge/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/programming/math_challenge/secgen_metadata.xml
index f7e86871f..67db33725 100644
--- a/modules/vulnerabilities/unix/ctf/programming/math_challenge/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/programming/math_challenge/secgen_metadata.xml
@@ -53,7 +53,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/programming/maze/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/programming/maze/secgen_metadata.xml
index c95b0e126..366ddd62c 100644
--- a/modules/vulnerabilities/unix/ctf/programming/maze/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/programming/maze/secgen_metadata.xml
@@ -49,7 +49,7 @@
https://github.com/itchyny/maze
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/pwn/bash_path_env_suid/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/pwn/bash_path_env_suid/secgen_metadata.xml
index 354d114d9..b7034a19b 100644
--- a/modules/vulnerabilities/unix/ctf/pwn/bash_path_env_suid/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/pwn/bash_path_env_suid/secgen_metadata.xml
@@ -60,7 +60,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/pwn/relative_path_suid_hardlinks/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/pwn/relative_path_suid_hardlinks/secgen_metadata.xml
index 3f237d904..ff4074edb 100644
--- a/modules/vulnerabilities/unix/ctf/pwn/relative_path_suid_hardlinks/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/pwn/relative_path_suid_hardlinks/secgen_metadata.xml
@@ -49,7 +49,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/pwn/ssh_leaked_keys/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/pwn/ssh_leaked_keys/secgen_metadata.xml
index ad88d8bb5..748eb976e 100644
--- a/modules/vulnerabilities/unix/ctf/pwn/ssh_leaked_keys/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/pwn/ssh_leaked_keys/secgen_metadata.xml
@@ -48,7 +48,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/pwn/symlinks/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/pwn/symlinks/secgen_metadata.xml
index 5c9c69a56..5d9fba39a 100644
--- a/modules/vulnerabilities/unix/ctf/pwn/symlinks/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/pwn/symlinks/secgen_metadata.xml
@@ -44,7 +44,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/pwn/two_shell_calls/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/pwn/two_shell_calls/secgen_metadata.xml
index c7fd9ffb2..117ce606a 100644
--- a/modules/vulnerabilities/unix/ctf/pwn/two_shell_calls/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/pwn/two_shell_calls/secgen_metadata.xml
@@ -60,7 +60,7 @@
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/ctf/reverse/java/java_decompile/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/reverse/java/java_decompile/secgen_metadata.xml
index e4607b282..e7a9f1a16 100644
--- a/modules/vulnerabilities/unix/ctf/reverse/java/java_decompile/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/ctf/reverse/java/java_decompile/secgen_metadata.xml
@@ -60,7 +60,7 @@
https://2013.picoctf.com
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
java
diff --git a/modules/vulnerabilities/unix/system/jtr_crackable_user_account/secgen_metadata.xml b/modules/vulnerabilities/unix/system/jtr_crackable_user_account/secgen_metadata.xml
index 0ecac7379..8b869884b 100644
--- a/modules/vulnerabilities/unix/system/jtr_crackable_user_account/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/system/jtr_crackable_user_account/secgen_metadata.xml
@@ -48,7 +48,7 @@
Use the following command: 'john -wordlist=/usr/share/john/password.lst yourhashfile'
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/modules/vulnerabilities/unix/system/ncrack_crackable_user_account/secgen_metadata.xml b/modules/vulnerabilities/unix/system/ncrack_crackable_user_account/secgen_metadata.xml
index 4d168c772..7b3b15b6d 100644
--- a/modules/vulnerabilities/unix/system/ncrack_crackable_user_account/secgen_metadata.xml
+++ b/modules/vulnerabilities/unix/system/ncrack_crackable_user_account/secgen_metadata.xml
@@ -47,7 +47,7 @@
Use the following command: 'ncrack -v --user username -P /usr/share/ncrack/default.pwd host_ip:22'
- utilities/unix/system/accounts
+ utilities/unix/system/.*/accounts
diff --git a/scenarios/examples/services_utilities_examples/user_test_scenario.xml b/scenarios/examples/services_utilities_examples/user_test_scenario.xml
index 3206ef7d6..f41295171 100644
--- a/scenarios/examples/services_utilities_examples/user_test_scenario.xml
+++ b/scenarios/examples/services_utilities_examples/user_test_scenario.xml
@@ -8,7 +8,7 @@
user_account_module_test
-
+