From 3bcdc902dce6c5bc46171c8585cb36e4ab4db896 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Wed, 10 Jul 2019 21:22:37 +0100 Subject: [PATCH] feat(semantic-release): implement for this formula * Based on `ssf-formula` (v0.3.0) - https://github.com/myii/ssf-formula/pull/5 * Unable to use `pillar.example` directly for testing - Used it as a basis for `test/salt/pillar/default.sls` - Brought useful changes back to `pillar.example` * Fix: avoid `users/googleauth.sls` for `RedHat` & `Suse` * Close #203 --- .gitignore | 122 +++++++++++ .travis.yml | 81 +++++++ FORMULA | 9 + Gemfile | 6 + README.rst | 69 ------ bin/kitchen | 29 +++ commitlint.config.js | 3 + docs/CONTRIBUTING.rst | 159 ++++++++++++++ docs/README.rst | 143 +++++++++++++ kitchen.yml | 151 +++++++++++++ pillar.example | 44 ++-- pre-commit_semantic-release.sh | 30 +++ release-rules.js | 18 ++ release.config.js | 106 ++++++++++ test/integration/default/README.md | 50 +++++ .../default/controls/config_spec.rb | 10 + test/integration/default/inspec.yml | 14 ++ test/salt/pillar/default.sls | 199 ++++++++++++++++++ users/googleauth.sls | 18 +- users/init.sls | 8 +- 20 files changed, 1167 insertions(+), 102 deletions(-) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 FORMULA create mode 100644 Gemfile delete mode 100644 README.rst create mode 100755 bin/kitchen create mode 100644 commitlint.config.js create mode 100644 docs/CONTRIBUTING.rst create mode 100644 docs/README.rst create mode 100644 kitchen.yml create mode 100755 pre-commit_semantic-release.sh create mode 100644 release-rules.js create mode 100644 release.config.js create mode 100644 test/integration/default/README.md create mode 100644 test/integration/default/controls/config_spec.rb create mode 100644 test/integration/default/inspec.yml create mode 100644 test/salt/pillar/default.sls diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbb03c --- /dev/null +++ b/.gitignore @@ -0,0 +1,122 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a packager +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.kitchen +.kitchen.local.yml +kitchen.local.yml +junit-*.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Bundler +Gemfile.lock + +# copied `.md` files used for conversion to `.rst` using `m2r` +docs/*.md + +# Vim +*.sw? + +## Collected when centralising formulas (check and sort) +# `collectd-formula` +.pytest_cache/ +/.idea/ +Dockerfile.*_* +ignore/ +tmp/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6205062 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +stages: + - test + - commitlint + - name: release + if: branch = master AND type != pull_request + +sudo: required +cache: bundler +language: ruby +dist: xenial + +services: + - docker + +# Make sure the instances listed below match up with +# the `platforms` defined in `kitchen.yml` +env: + matrix: + - INSTANCE: default-debian-10-develop-py3 + # - INSTANCE: default-ubuntu-1804-develop-py3 + # - INSTANCE: default-centos-7-develop-py3 + # - INSTANCE: default-fedora-30-develop-py3 + # - INSTANCE: default-opensuse-leap-15-develop-py3 + # - INSTANCE: default-amazonlinux-2-develop-py2 + # - INSTANCE: default-debian-9-2019-2-py3 + - INSTANCE: default-ubuntu-1804-2019-2-py3 + # - INSTANCE: default-centos-7-2019-2-py3 + # - INSTANCE: default-fedora-30-2019-2-py3 + # - INSTANCE: default-opensuse-leap-15-2019-2-py3 + - INSTANCE: default-amazonlinux-2-2019-2-py2 + # - INSTANCE: default-debian-9-2018-3-py2 + # - INSTANCE: default-ubuntu-1604-2018-3-py2 + # - INSTANCE: default-centos-7-2018-3-py2 + - INSTANCE: default-fedora-29-2018-3-py2 + - INSTANCE: default-opensuse-leap-15-2018-3-py2 + # - INSTANCE: default-amazonlinux-2-2018-3-py2 + # - INSTANCE: default-debian-8-2017-7-py2 + # - INSTANCE: default-ubuntu-1604-2017-7-py2 + - INSTANCE: default-centos-6-2017-7-py2 + # - INSTANCE: default-fedora-29-2017-7-py2 + # - INSTANCE: default-opensuse-leap-15-2017-7-py2 + # - INSTANCE: default-amazonlinux-2-2017-7-py2 + +script: + - bin/kitchen verify ${INSTANCE} + +jobs: + include: + # Define the commitlint stage + - stage: commitlint + language: node_js + node_js: lts/* + before_install: skip + script: + - npm install @commitlint/config-conventional -D + - npm install @commitlint/travis-cli -D + - commitlint-travis + # Define the release stage that runs semantic-release + - stage: release + language: node_js + node_js: lts/* + before_install: skip + script: + # Update `AUTHORS.md` + - export MAINTAINER_TOKEN=${GH_TOKEN} + - go get github.com/myii/maintainer + - maintainer contributor + + # Install all dependencies required for `semantic-release` + - npm install @semantic-release/changelog@3 -D + - npm install @semantic-release/exec@3 -D + - npm install @semantic-release/git@7 -D + deploy: + provider: script + skip_cleanup: true + script: + # Run `semantic-release` + - npx semantic-release@15 diff --git a/FORMULA b/FORMULA new file mode 100644 index 0000000..6b8b06e --- /dev/null +++ b/FORMULA @@ -0,0 +1,9 @@ +name: users +os: Debian, Ubuntu, Raspbian, RedHat, Fedora, CentOS, Suse, openSUSE, Gentoo, Funtoo, Arch, Manjaro, Alpine, FreeBSD, OpenBSD, Solaris, SmartOS, Windows, MacOS +os_family: Debian, RedHat, Suse, Gentoo, Arch, Alpine, FreeBSD, OpenBSD, Solaris, Windows, MacOS +version: 0.46.1 +release: 1 +minimum_version: 2017.7 +summary: users formula +description: Formula to configure users via pillar +top_level_dir: users diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..3b36de3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem 'kitchen-docker', '>= 2.9' +gem 'kitchen-salt', '>= 0.6.0' +gem 'kitchen-inspec', '>= 1.1' + diff --git a/README.rst b/README.rst deleted file mode 100644 index 39f9cf7..0000000 --- a/README.rst +++ /dev/null @@ -1,69 +0,0 @@ -===== -users -===== - -Formula to configure users via pillar. - - -.. note:: - - See the full `Salt Formulas installation and usage instructions - `_. - -Available states -================ - -.. contents:: - :local: - -``users`` ---------- - -Configures a user's home directory, group, the user itself, secondary groups, -and associated keys. Also configures sudo access, and absent users. - -``users.sudo`` --------------- - -Ensures the sudo group exists, the sudo package is installed and the sudo file -is configured. - -``users.bashrc`` ----------------- - -Ensures the bashrc file exists in the users home directory. Sets 'manage_bashrc: -True' in pillar per user. Defaults to False. - -``users.profile`` ----------------- - -Ensures the profile file exists in the users home directory. Sets 'manage_profile: -True' in pillar per user. Defaults to False. - -``users.vimrc`` ---------------- - -Ensures the vimrc file exists in the users home directory. Sets 'manage_vimrc: -True' in pillar per user. Defaults to False. -This depends on the vim-formula being available and pillar `users:use_vim_formula: True`. - -``users.user_files`` ---------------- - -Permits the abitrary management of files. See pillar.example for configuration details. - -Overriding default values -========================= - -In order to separate actual user account definitions from configuration the pillar ``users-formula`` was introduced: - -.. code-block:: yaml - - users: - myuser: - # stuff - - users-formula: - lookup: - root_group: toor - shell: '/bin/zsh' diff --git a/bin/kitchen b/bin/kitchen new file mode 100755 index 0000000..1cd44f3 --- /dev/null +++ b/bin/kitchen @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kitchen' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("test-kitchen", "kitchen") diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..2f9d1aa --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/docs/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst new file mode 100644 index 0000000..b7da8f4 --- /dev/null +++ b/docs/CONTRIBUTING.rst @@ -0,0 +1,159 @@ +.. _contributing: + +How to contribute +================= + +This document will eventually outline all aspects of guidance to make your contributing experience a fruitful and enjoyable one. +What it already contains is information about *commit message formatting* and how that directly affects the numerous automated processes that are used for this repo. +It also covers how to contribute to this *formula's documentation*. + +.. contents:: **Table of Contents** + +Overview +-------- + +Submitting a pull request is more than just code! +To achieve a quality product, the *tests* and *documentation* need to be updated as well. +An excellent pull request will include these in the changes, wherever relevant. + +Commit message formatting +------------------------- + +Since every type of change requires making Git commits, +we will start by covering the importance of ensuring that all of your commit +messages are in the correct format. + +Automation of multiple processes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This formula uses `semantic-release `_ for automating numerous processes such as bumping the version number appropriately, creating new tags/releases and updating the changelog. +The entire process relies on the structure of commit messages to determine the version bump, which is then used for the rest of the automation. + +Full details are available in the upstream docs regarding the `Angular Commit Message Conventions `_. +The key factor is that the first line of the commit message must follow this format: + +.. code-block:: + + type(scope): subject + + +* E.g. ``docs(contributing): add commit message formatting instructions``. + +Besides the version bump, the changelog and release notes are formatted accordingly. +So based on the example above: + +.. + + .. raw:: html + +

Documentation

+ + * **contributing:** add commit message formatting instructions + + +* The ``type`` translates into a ``Documentation`` sub-heading. +* The ``(scope):`` will be shown in bold text without the brackets. +* The ``subject`` follows the ``scope`` as standard text. + +Linting commit messages in Travis CI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This formula uses `commitlint `_ for checking commit messages during CI testing. +This ensures that they are in accordance with the ``semantic-release`` settings. + +For more details about the default settings, refer back to the ``commitlint`` `reference rules `_. + +Relationship between commit type and version bump +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This formula applies some customisations to the defaults, as outlined in the table below, +based upon the `type `_ of the commit: + +.. list-table:: + :name: commit-type-vs-version-bump + :header-rows: 1 + :stub-columns: 0 + :widths: 1,2,3,1,1 + + * - Type + - Heading + - Description + - Bump (default) + - Bump (custom) + * - ``build`` + - Build System + - Changes related to the build system + - – + - + * - ``chore`` + - – + - Changes to the build process or auxiliary tools and libraries such as + documentation generation + - – + - + * - ``ci`` + - Continuous Integration + - Changes to the continuous integration configuration + - – + - + * - ``docs`` + - Documentation + - Documentation only changes + - – + - 0.0.1 + * - ``feat`` + - Features + - A new feature + - 0.1.0 + - + * - ``fix`` + - Bug Fixes + - A bug fix + - 0.0.1 + - + * - ``perf`` + - Performance Improvements + - A code change that improves performance + - 0.0.1 + - + * - ``refactor`` + - Code Refactoring + - A code change that neither fixes a bug nor adds a feature + - – + - 0.0.1 + * - ``revert`` + - Reverts + - A commit used to revert a previous commit + - – + - 0.0.1 + * - ``style`` + - Styles + - Changes that do not affect the meaning of the code (white-space, + formatting, missing semi-colons, etc.) + - – + - 0.0.1 + * - ``test`` + - Tests + - Adding missing or correcting existing tests + - – + - 0.0.1 + +Use ``BREAKING CHANGE`` to trigger a ``major`` version change +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Adding ``BREAKING CHANGE`` to the footer of the extended description of the commit message will **always** trigger a ``major`` version change, no matter which type has been used. +This will be appended to the changelog and release notes as well. +To preserve good formatting of these notes, the following format is prescribed: + +* ``BREAKING CHANGE: .`` + +An example of that: + +.. code-block:: git + + ... + + BREAKING CHANGE: With the removal of all of the `.sls` files under + `template package`, this formula no longer supports the installation of + packages. + diff --git a/docs/README.rst b/docs/README.rst new file mode 100644 index 0000000..1ab047a --- /dev/null +++ b/docs/README.rst @@ -0,0 +1,143 @@ +.. _readme: + +users +===== + +|img_travis| |img_sr| + +.. |img_travis| image:: https://travis-ci.com/saltstack-formulas/users-formula.svg?branch=master + :alt: Travis CI Build Status + :scale: 100% + :target: https://travis-ci.com/saltstack-formulas/users-formula +.. |img_sr| image:: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg + :alt: Semantic Release + :scale: 100% + :target: https://github.com/semantic-release/semantic-release + +Formula to configure users via pillar. + +.. contents:: **Table of Contents** + +General notes +------------- + +See the full `SaltStack Formulas installation and usage instructions +`_. + +If you are interested in writing or contributing to formulas, please pay attention to the `Writing Formula Section +`_. + +If you want to use this formula, please pay attention to the ``FORMULA`` file and/or ``git tag``, +which contains the currently released version. This formula is versioned according to `Semantic Versioning `_. + +See `Formula Versioning Section `_ for more details. + +Contributing to this repo +------------------------- + +**Commit message formatting is significant!!** + +Please see :ref:`How to contribute ` for more details. + +Available states +---------------- + +.. contents:: + :local: + +``users`` +^^^^^^^^^ + +Configures a user's home directory, group, the user itself, secondary groups, +and associated keys. Also configures sudo access, and absent users. + +``users.sudo`` +^^^^^^^^^^^^^^ + +Ensures the sudo group exists, the sudo package is installed and the sudo file +is configured. + +``users.bashrc`` +^^^^^^^^^^^^^^^^ + +Ensures the bashrc file exists in the users home directory. Sets 'manage_bashrc: +True' in pillar per user. Defaults to False. + +``users.profile`` +^^^^^^^^^^^^^^^^ + +Ensures the profile file exists in the users home directory. Sets 'manage_profile: +True' in pillar per user. Defaults to False. + +``users.vimrc`` +^^^^^^^^^^^^^^^ + +Ensures the vimrc file exists in the users home directory. Sets 'manage_vimrc: +True' in pillar per user. Defaults to False. +This depends on the vim-formula being available and pillar `users:use_vim_formula: True`. + +``users.user_files`` +^^^^^^^^^^^^^^^^^^^^ + +Permits the abitrary management of files. See pillar.example for configuration details. + +Overriding default values +------------------------- + +In order to separate actual user account definitions from configuration the pillar ``users-formula`` was introduced: + +.. code-block:: yaml + + users: + myuser: + # stuff + + users-formula: + lookup: + root_group: toor + shell: '/bin/zsh' + +Testing +------- + +Linux testing is done with ``kitchen-salt``. + +Requirements +^^^^^^^^^^^^ + +* Ruby +* Docker + +.. code-block:: bash + + $ gem install bundler + $ bundle install + $ bin/kitchen test [platform] + +Where ``[platform]`` is the platform name defined in ``kitchen.yml``, +e.g. ``debian-9-2019-2-py3``. + +``bin/kitchen converge`` +^^^^^^^^^^^^^^^^^^^^^^^^ + +Creates the docker instance and runs the ``template`` main state, ready for testing. + +``bin/kitchen verify`` +^^^^^^^^^^^^^^^^^^^^^^ + +Runs the ``inspec`` tests on the actual instance. + +``bin/kitchen destroy`` +^^^^^^^^^^^^^^^^^^^^^^^ + +Removes the docker instance. + +``bin/kitchen test`` +^^^^^^^^^^^^^^^^^^^^ + +Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``verify`` + ``destroy``. + +``bin/kitchen login`` +^^^^^^^^^^^^^^^^^^^^^ + +Gives you SSH access to the instance for manual testing. diff --git a/kitchen.yml b/kitchen.yml new file mode 100644 index 0000000..2d1edbb --- /dev/null +++ b/kitchen.yml @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# For help on this file's format, see https://kitchen.ci/ +driver: + name: docker + use_sudo: false + privileged: true + run_command: /lib/systemd/systemd + +# Make sure the platforms listed below match up with +# the `env.matrix` instances defined in `.travis.yml` +platforms: + ## SALT `develop` + - name: debian-10-develop-py3 + driver: + image: netmanagers/salt-develop-py3:debian-10 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: ubuntu-1804-develop-py3 + driver: + image: netmanagers/salt-develop-py3:ubuntu-18.04 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: centos-7-develop-py3 + driver: + image: netmanagers/salt-develop-py3:centos-7 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: fedora-30-develop-py3 + driver: + image: netmanagers/salt-develop-py3:fedora-30 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: opensuse-leap-15-develop-py3 + driver: + image: netmanagers/salt-develop-py3:opensuse-leap-15 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + run_command: /usr/lib/systemd/systemd + - name: amazonlinux-2-develop-py2 + driver: + image: netmanagers/salt-develop-py2:amazonlinux-2 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python2 git develop + + ## SALT `2019.2` + - name: debian-9-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:debian-9 + - name: ubuntu-1804-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:ubuntu-18.04 + - name: centos-7-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:centos-7 + - name: fedora-30-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:fedora-30 + - name: opensuse-leap-15-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:opensuse-leap-15 + run_command: /usr/lib/systemd/systemd + - name: amazonlinux-2-2019-2-py2 + driver: + image: netmanagers/salt-2019.2-py2:amazonlinux-2 + + ## SALT `2018.3` + - name: debian-9-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:debian-9 + - name: ubuntu-1604-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:ubuntu-16.04 + - name: centos-7-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:centos-7 + - name: fedora-29-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:fedora-29 + - name: opensuse-leap-15-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:opensuse-leap-15 + run_command: /usr/lib/systemd/systemd + - name: amazonlinux-2-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:amazonlinux-2 + + ## SALT `2017.7` + - name: debian-8-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:debian-8 + - name: ubuntu-1604-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:ubuntu-16.04 + - name: centos-6-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:centos-6 + run_command: /sbin/init + - name: fedora-29-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:fedora-29 + - name: opensuse-leap-15-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:opensuse-leap-15 + run_command: /usr/lib/systemd/systemd + - name: amazonlinux-2-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:amazonlinux-2 + +provisioner: + name: salt_solo + log_level: info + salt_install: none + require_chef: false + formula: users + salt_copy_filter: + - .kitchen + - .git + +verifier: + # https://www.inspec.io/ + name: inspec + sudo: true + # cli, documentation, html, progress, json, json-min, json-rspec, junit + reporter: + - cli + +suites: + - name: default + provisioner: + state_top: + base: + '*': + - users + pillars: + top.sls: + base: + '*': + - users + pillars_from_files: + users.sls: test/salt/pillar/default.sls + verifier: + inspec_tests: + - path: test/integration/default diff --git a/pillar.example b/pillar.example index 7d6ebc7..9af2984 100644 --- a/pillar.example +++ b/pillar.example @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- users-formula: use_vim_formula: True lookup: # override the defauls in map.jinja @@ -7,8 +10,20 @@ users-formula: groups: foo: state: present - gid: 500 + gid: 1500 system: False + badguys: + absent: True + niceguys: + gid: 4242 + system: False + addusers: root + delusers: toor + ssl-cert: + system: True + members: + - www-data + - openldap users: ## Minimal required pillar values @@ -16,7 +31,6 @@ users: fullname: A User ## Full list of pillar values - allow_gid_change: False buser: fullname: B User password: $6$w............. @@ -35,7 +49,7 @@ users: workphone: "(555) 555-5555" homephone: "(555) 555-5551" manage_vimrc: False - allow_gid_change: True + allow_gid_change: False manage_bashrc: False manage_profile: False expire: 16426 @@ -61,7 +75,7 @@ users: remove_groups: False prime_group: name: primarygroup - gid: 500 + gid: 1501 groups: - users optional_groups: @@ -138,7 +152,7 @@ users: google_2fa: True google_auth: - ssh: | + sshd: | SOMEGAUTHHASHVAL " RESETTING_TIME_SKEW 46956472+2 46991595-2 " RATE_LIMIT 3 30 1415800560 @@ -158,14 +172,14 @@ users: # 'source' allows you to define an arbitrary directory to sync, useful to use for default files. # should be a salt fileserver path either with or without 'salt://' # if not present, it defaults to 'salt://users/files/user/ - source: users/files/default - template: jinja + source: users/files + # template: jinja # You can specify octal mode for files and symlinks that will be copied. Since version 2016.11.0 # it's possible to use 'keep' for file_mode, to preserve file original mode, thus you can save # execution bit for example. file_mode: keep # You can specify octal mode for directories as well. This won't work on Windows minions - #dir_mode: 775 + # dir_mode: 775 sym_mode: 640 exclude_pat: "*.gitignore" @@ -180,17 +194,3 @@ users: absent_users: - donald - bad_guy - -groups: - badguys: - absent: True - niceguys: - gid: 4242 - system: False - addusers: root - delusers: toor - ssl-cert: - system: True - members: - - www-data - - openldap diff --git a/pre-commit_semantic-release.sh b/pre-commit_semantic-release.sh new file mode 100755 index 0000000..9d34d74 --- /dev/null +++ b/pre-commit_semantic-release.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +############################################################################### +# (A) Update `FORMULA` with `${nextRelease.version}` +############################################################################### +sed -i -e "s_^\(version:\).*_\1 ${1}_" FORMULA + + +############################################################################### +# (B) Use `m2r` to convert automatically produced `.md` docs to `.rst` +############################################################################### + +# Install `m2r` +sudo -H pip install m2r + +# Copy and then convert the `.md` docs +cp *.md docs/ +cd docs/ +m2r --overwrite *.md + +# Change excess `H1` headings to `H2` in converted `CHANGELOG.rst` +sed -i -e '/^=.*$/s/=/-/g' CHANGELOG.rst +sed -i -e '1,4s/-/=/g' CHANGELOG.rst + +# Use for debugging output, when required +# cat AUTHORS.rst +# cat CHANGELOG.rst + +# Return back to the main directory +cd .. diff --git a/release-rules.js b/release-rules.js new file mode 100644 index 0000000..c63c850 --- /dev/null +++ b/release-rules.js @@ -0,0 +1,18 @@ +// No release is triggered for the types commented out below. +// Commits using these types will be incorporated into the next release. +// +// NOTE: Any changes here must be reflected in `CONTRIBUTING.md`. +module.exports = [ + {breaking: true, release: 'major'}, + // {type: 'build', release: 'patch'}, + // {type: 'chore', release: 'patch'}, + // {type: 'ci', release: 'patch'}, + {type: 'docs', release: 'patch'}, + {type: 'feat', release: 'minor'}, + {type: 'fix', release: 'patch'}, + {type: 'perf', release: 'patch'}, + {type: 'refactor', release: 'patch'}, + {type: 'revert', release: 'patch'}, + {type: 'style', release: 'patch'}, + {type: 'test', release: 'patch'}, +]; diff --git a/release.config.js b/release.config.js new file mode 100644 index 0000000..afa0cb1 --- /dev/null +++ b/release.config.js @@ -0,0 +1,106 @@ +module.exports = { + branch: 'master', + plugins: [ + ['@semantic-release/commit-analyzer', { + preset: 'angular', + releaseRules: './release-rules.js', + }], + '@semantic-release/release-notes-generator', + ['@semantic-release/changelog', { + changelogFile: 'CHANGELOG.md', + changelogTitle: '# Changelog', + }], + ['@semantic-release/exec', { + prepareCmd: 'sh ./pre-commit_semantic-release.sh ${nextRelease.version}', + }], + ['@semantic-release/git', { + assets: ['*.md', 'docs/*.rst', 'FORMULA'], + }], + '@semantic-release/github', + ], + generateNotes: { + preset: 'angular', + writerOpts: { + // Required due to upstream bug preventing all types being displayed. + // Bug: https://github.com/conventional-changelog/conventional-changelog/issues/317 + // Fix: https://github.com/conventional-changelog/conventional-changelog/pull/410 + transform: (commit, context) => { + const issues = [] + + commit.notes.forEach(note => { + note.title = `BREAKING CHANGES` + }) + + // NOTE: Any changes here must be reflected in `CONTRIBUTING.md`. + if (commit.type === `feat`) { + commit.type = `Features` + } else if (commit.type === `fix`) { + commit.type = `Bug Fixes` + } else if (commit.type === `perf`) { + commit.type = `Performance Improvements` + } else if (commit.type === `revert`) { + commit.type = `Reverts` + } else if (commit.type === `docs`) { + commit.type = `Documentation` + } else if (commit.type === `style`) { + commit.type = `Styles` + } else if (commit.type === `refactor`) { + commit.type = `Code Refactoring` + } else if (commit.type === `test`) { + commit.type = `Tests` + } else if (commit.type === `build`) { + commit.type = `Build System` + // } else if (commit.type === `chore`) { + // commit.type = `Maintenance` + } else if (commit.type === `ci`) { + commit.type = `Continuous Integration` + } else { + return + } + + if (commit.scope === `*`) { + commit.scope = `` + } + + if (typeof commit.hash === `string`) { + commit.hash = commit.hash.substring(0, 7) + } + + if (typeof commit.subject === `string`) { + let url = context.repository + ? `${context.host}/${context.owner}/${context.repository}` + : context.repoUrl + if (url) { + url = `${url}/issues/` + // Issue URLs. + commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => { + issues.push(issue) + return `[#${issue}](${url}${issue})` + }) + } + if (context.host) { + // User URLs. + commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => { + if (username.includes('/')) { + return `@${username}` + } + + return `[@${username}](${context.host}/${username})` + }) + } + } + + // remove references that already appear in the subject + commit.references = commit.references.filter(reference => { + if (issues.indexOf(reference.issue) === -1) { + return true + } + + return false + }) + + return commit + }, + }, + }, +}; diff --git a/test/integration/default/README.md b/test/integration/default/README.md new file mode 100644 index 0000000..37cf963 --- /dev/null +++ b/test/integration/default/README.md @@ -0,0 +1,50 @@ +# InSpec Profile: `default` + +This shows the implementation of the `default` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md). + +## Verify a profile + +InSpec ships with built-in features to verify a profile structure. + +```bash +$ inspec check default +Summary +------- +Location: default +Profile: profile +Controls: 4 +Timestamp: 2019-06-24T23:09:01+00:00 +Valid: true + +Errors +------ + +Warnings +-------- +``` + +## Execute a profile + +To run all **supported** controls on a local machine use `inspec exec /path/to/profile`. + +```bash +$ inspec exec default +.. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +8 examples, 0 failures +``` + +## Execute a specific control from a profile + +To run one control from the profile use `inspec exec /path/to/profile --controls name`. + +```bash +$ inspec exec default --controls package +. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +1 examples, 0 failures +``` + +See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb). diff --git a/test/integration/default/controls/config_spec.rb b/test/integration/default/controls/config_spec.rb new file mode 100644 index 0000000..d89c35f --- /dev/null +++ b/test/integration/default/controls/config_spec.rb @@ -0,0 +1,10 @@ +control 'users configuration' do + title 'should match desired lines' + + describe file('/custom/buser') do + its('type') { should eq :directory } + it { should be_owned_by 'buser' } + it { should be_grouped_into 'primarygroup' } + its('mode') { should cmp '0750' } + end +end diff --git a/test/integration/default/inspec.yml b/test/integration/default/inspec.yml new file mode 100644 index 0000000..fd3ee7c --- /dev/null +++ b/test/integration/default/inspec.yml @@ -0,0 +1,14 @@ +name: default +title: users formula +maintainer: SaltStack Formulas +license: Apache-2.0 +summary: Verify that the users formula is setup and configured correctly +supports: + - platform-name: debian + - platform-name: ubuntu + - platform-name: centos + - platform-name: fedora + - platform-name: opensuse + - platform-name: suse + - platform-name: freebsd + - platform-name: amazon diff --git a/test/salt/pillar/default.sls b/test/salt/pillar/default.sls new file mode 100644 index 0000000..392af00 --- /dev/null +++ b/test/salt/pillar/default.sls @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +users-formula: + use_vim_formula: true + lookup: # override the defauls in map.jinja + root_group: root + +# group initialization +groups: + foo: + state: present + gid: 1500 + system: false + badguys: + absent: true + niceguys: + gid: 4242 + system: false + addusers: root + delusers: toor + ssl-cert: + system: true + members: + # *TODO*: run groups after all users created and then use `auser` and `buser` instead + - root + - sshd + # - bin + # - daemon + +users: + ## Minimal required pillar values + auser: + fullname: A User + + ## Full list of pillar values + buser: + fullname: B User + password: $6$w............. + enforce_password: true + # WARNING: If 'empty_password' is set to true, the 'password' statement + # will be ignored by enabling password-less login for the user. + empty_password: false + hash_password: false + system: false + home: /custom/buser + homedir_owner: buser + homedir_group: primarygroup + user_dir_mode: 750 + createhome: true + roomnumber: "A-1" + workphone: "(555) 555-5555" + homephone: "(555) 555-5551" + manage_vimrc: false + allow_gid_change: false + manage_bashrc: false + manage_profile: false + expire: 16426 + # Disables user management except sudo rules. + # Useful for setting sudo rules for system accounts created by package instalation + sudoonly: false + sudouser: true + # sudo_rules doesn't need the username as a prefix for the rule + # this is added automatically by the formula. + # ---------------------------------------------------------------------- + # In case your sudo_rules have a colon please have in mind to not leave + # spaces around it. For example: + # ALL=(ALL) NOPASSWD: ALL <--- THIS WILL NOT WORK (Besides syntax is ok) + # ALL=(ALL) NOPASSWD:ALL <--- THIS WILL WORK + sudo_rules: + - ALL=(root) /usr/bin/find + - ALL=(otheruser) /usr/bin/script.sh + sudo_defaults: + - '!requiretty' + # enable polkitadmin to make user an AdminIdentity for polkit + polkitadmin: true + shell: /bin/bash + remove_groups: false + prime_group: + name: primarygroup + gid: 1501 + groups: + - users + optional_groups: + - some_groups_that_might + - not_exist_on_all_minions + ssh_key_type: rsa + # # You can inline the private keys ... + # ssh_keys: + # privkey: PRIVATEKEY + # pubkey: PUBLICKEY + # # or you can provide path to key on Salt fileserver + # # privkey: salt://path_to_PRIVATEKEY + # # pubkey: salt://path_to_PUBLICKEY + # # you can provide multiple keys, the keyname is taken as filename + # # make sure your public keys suffix is .pub + # foobar: PRIVATEKEY + # foobar.pub: PUBLICKEY + # # ... or you can pull them from a different pillar, + # # for example one called "ssh_keys": + # ssh_keys_pillar: + # id_rsa: "ssh_keys" + # another_key_pair: "ssh_keys" + # ssh_auth: + # - PUBLICKEY + # ssh_auth.absent: + # - PUBLICKEY_TO_BE_REMOVED + # # Generates an authorized_keys file for the user + # # with the given keys + # ssh_auth_file: + # - PUBLICKEY + # # ... or you can pull them from a different pillar similar to ssh_keys_pillar + # ssh_auth_pillar: + # id_rsa: "ssh_keys" + # # If you prefer to keep public keys as files rather + # # than inline in pillar, this works. + # ssh_auth_sources: + # - salt://keys/buser.id_rsa.pub + # ssh_auth_sources.absent: + # - salt://keys/deleteduser.id_rsa.pub # PUBLICKEY_FILE_TO_BE_REMOVED + # Manage the ~/.ssh/config file + ssh_known_hosts: + importanthost: + port: 22 + fingerprint: 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 + key: PUBLICKEY + enc: ssh-rsa + hash_known_hosts: true + timeout: 5 + fingerprint_hash_type: sha256 + ssh_known_hosts.absent: + - notimportanthost + ssh_config: + all: + hostname: "*" + options: + - "StrictHostKeyChecking no" + - "UserKnownHostsFile=/dev/null" + importanthost: + hostname: "needcheck.example.com" + options: + - "StrictHostKeyChecking yes" + + # Using gitconfig without Git installed will result in an error + # https://docs.saltstack.com/en/latest/ref/states/all/salt.states.git.html: + # This state module now requires git 1.6.5 (released 10 October 2009) or newer. + gitconfig: + user.name: B User + user.email: buser@example.com + "url.https://.insteadOf": "git://" + + gitconfig.absent: + - push.default + - color\..+ + + google_2fa: true + google_auth: + sshd: | + SOMEGAUTHHASHVAL + " RESETTING_TIME_SKEW 46956472+2 46991595-2 + " RATE_LIMIT 3 30 1415800560 + " DISALLOW_REUSE 47193352 + " TOTP_AUTH + 11111111 + 22222222 + 33333333 + 44444444 + 55555555 + # unique: true allows user to have non unique uid + unique: false + uid: 1001 + + user_files: + enabled: true + # 'source' allows you to define an arbitrary directory to sync, useful to use for default files. + # should be a salt fileserver path either with or without 'salt://' + # if not present, it defaults to 'salt://users/files/user/ + source: users/files + # template: jinja + # You can specify octal mode for files and symlinks that will be copied. Since version 2016.11.0 + # it's possible to use 'keep' for file_mode, to preserve file original mode, thus you can save + # execution bit for example. + file_mode: keep + # You can specify octal mode for directories as well. This won't work on Windows minions + # dir_mode: 775 + sym_mode: 640 + exclude_pat: "*.gitignore" + + ## Absent user + cuser: + absent: true + purge: true + force: true + + +## Old syntax of absent_users still supported +absent_users: + - donald + - bad_guy diff --git a/users/googleauth.sls b/users/googleauth.sls index 9e6a9ff..3f59c8f 100644 --- a/users/googleauth.sls +++ b/users/googleauth.sls @@ -1,6 +1,7 @@ # vim: sts=2 ts=2 sw=2 et ai -{% from "users/map.jinja" import users with context %} +{%- from "users/map.jinja" import users with context %} +{%- if not grains['os_family'] in ['RedHat', 'Suse'] %} users_googleauth-package: pkg.installed: - name: {{ users.googleauth_package }} @@ -14,10 +15,10 @@ users_{{ users.googleauth_dir }}: - group: {{ users.root_group }} - mode: 600 -{% for name, user in pillar.get('users', {}).items() if user.absent is not defined or not user.absent %} -{%- if 'google_auth' in user %} -{%- for svc in user['google_auth'] %} -{%- if user.get('google_2fa', True) %} +{%- for name, user in pillar.get('users', {}).items() if user.absent is not defined or not user.absent %} +{%- if 'google_auth' in user %} +{%- for svc in user['google_auth'] %} +{%- if user.get('google_2fa', True) %} users_googleauth-pam-{{ svc }}-{{ name }}: file.replace: - name: /etc/pam.d/{{ svc }} @@ -25,7 +26,8 @@ users_googleauth-pam-{{ svc }}-{{ name }}: - repl: "auth [success=done new_authtok_reqd=done default=die] pam_google_authenticator.so user=root secret={{ users.googleauth_dir }}/${USER}_{{ svc }} echo_verification_code\n@include common-auth" - unless: grep pam_google_authenticator.so /etc/pam.d/{{ svc }} - backup: .bak +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endfor %} {%- endif %} -{%- endfor %} -{%- endif %} -{%- endfor %} diff --git a/users/init.sls b/users/init.sls index 19c8e8e..21df048 100644 --- a/users/init.sls +++ b/users/init.sls @@ -506,8 +506,9 @@ users_{{ users.sudoers_dir }}/{{ sudoers_d_filename }}: - name: {{ users.sudoers_dir }}/{{ sudoers_d_filename }} {% endif %} -{%- if 'google_auth' in user %} -{%- for svc in user['google_auth'] %} +{%- if not grains['os_family'] in ['RedHat', 'Suse'] %} +{%- if 'google_auth' in user %} +{%- for svc in user['google_auth'] %} users_googleauth-{{ svc }}-{{ name }}: file.managed: - replace: false @@ -518,7 +519,8 @@ users_googleauth-{{ svc }}-{{ name }}: - mode: 400 - require: - pkg: users_googleauth-package -{%- endfor %} +{%- endfor %} +{%- endif %} {%- endif %} # this doesn't work (Salt bug), therefore need to run state.apply twice