├── .github └── workflows │ ├── commitlint.yml │ ├── kitchen.vagrant.yml │ └── kitchen.windows.yml ├── .gitignore ├── .gitlab-ci.yml ├── .pre-commit-config.yaml ├── .rstcheck.cfg ├── .rubocop.yml ├── .salt-lint ├── .travis.yml ├── .yamllint ├── AUTHORS.md ├── CHANGELOG.md ├── CODEOWNERS ├── FORMULA ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── bin ├── install-hooks └── kitchen ├── commitlint.config.js ├── docs ├── AUTHORS.rst ├── CHANGELOG.rst ├── README.rst └── map.jinja.rst ├── kitchen.vagrant.yml ├── kitchen.windows.yml ├── kitchen.yml ├── openvpn ├── _mapdata │ ├── _mapdata.jinja │ └── init.sls ├── adapters.sls ├── config.sls ├── dhparams.sls ├── files │ ├── client.jinja │ ├── common_opts.jinja │ ├── ifconfig_pool_persist.jinja │ ├── openvpn-1.cer │ ├── openvpn-2.cer │ ├── peer.jinja │ ├── server.jinja │ └── tap-adapter.ps1 ├── general_config.sls ├── gui.sls ├── hardening.sls ├── ifconfig_pool_persist.sls ├── init.sls ├── install.sls ├── libmapstack.jinja ├── libmatchers.jinja ├── libsaltcli.jinja ├── macros.jinja ├── map.jinja ├── network_manager_networks │ ├── files │ │ └── connection.jinja │ └── init.sls ├── parameters │ ├── defaults.yaml │ ├── defaults.yaml.jinja │ ├── map_jinja.yaml │ ├── os │ │ ├── Debian.yaml │ │ ├── Fedora.yaml │ │ └── Ubuntu.yaml │ ├── os_family │ │ ├── Arch.yaml │ │ ├── Debian.yaml │ │ ├── FreeBSD.yaml │ │ ├── RedHat.yaml │ │ └── Windows.yaml │ ├── oscodename │ │ └── openSUSE Tumbleweed.yaml │ └── osfinger │ │ └── CentOS-6.yaml ├── repo.sls └── service.sls ├── pillar.example ├── pre-commit_semantic-release.sh ├── release-rules.js ├── release.config.js └── test ├── integration ├── default │ ├── README.md │ ├── controls │ │ ├── _mapdata.rb │ │ ├── config_spec.rb │ │ ├── packages_spec.rb │ │ └── services_spec.rb │ ├── files │ │ └── _mapdata │ │ │ ├── amazonlinux-1.yaml │ │ │ ├── amazonlinux-2.yaml │ │ │ ├── arch-base-latest.yaml │ │ │ ├── centos-6.yaml │ │ │ ├── centos-7.yaml │ │ │ ├── centos-8.yaml │ │ │ ├── debian-10.yaml │ │ │ ├── debian-11.yaml │ │ │ ├── debian-9.yaml │ │ │ ├── fedora-31.yaml │ │ │ ├── fedora-32.yaml │ │ │ ├── fedora-33.yaml │ │ │ ├── gentoo-2-sysd.yaml │ │ │ ├── gentoo-2-sysv.yaml │ │ │ ├── opensuse-15.yaml │ │ │ ├── opensuse-tumbleweed.yaml │ │ │ ├── oraclelinux-7.yaml │ │ │ ├── oraclelinux-8.yaml │ │ │ ├── ubuntu-16.yaml │ │ │ ├── ubuntu-18.yaml │ │ │ ├── ubuntu-20.yaml │ │ │ ├── ubuntu-22.yaml │ │ │ ├── windows-10.yaml │ │ │ ├── windows-2016-server.yaml │ │ │ ├── windows-2019-server.yaml │ │ │ ├── windows-2022-server.yaml │ │ │ └── windows-8.yaml │ └── inspec.yml └── share │ ├── README.md │ ├── inspec.yml │ └── libraries │ └── system.rb └── salt └── pillar └── default.sls /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | name: Commitlint 5 | 'on': [pull_request] 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | env: 11 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | - uses: wagoid/commitlint-github-action@v1 17 | -------------------------------------------------------------------------------- /.github/workflows/kitchen.vagrant.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | name: 'Kitchen Vagrant (Windows)' 5 | 'on': ['push', 'pull_request'] 6 | 7 | env: 8 | KITCHEN_LOCAL_YAML: 'kitchen.vagrant.yml' 9 | 10 | jobs: 11 | test: 12 | runs-on: 'macos-10.15' 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | instance: 17 | - default-windows-10-latest-py3 18 | - default-windows-81-latest-py3 19 | steps: 20 | - name: 'Check out code' 21 | uses: 'actions/checkout@v2' 22 | - name: 'Set up Bundler cache' 23 | uses: 'actions/cache@v1' 24 | with: 25 | path: 'vendor/bundle' 26 | key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" 27 | restore-keys: "${{ runner.os }}-gems-" 28 | - name: 'Run Bundler' 29 | run: | 30 | ruby --version 31 | bundle config path vendor/bundle 32 | bundle install --jobs 4 --retry 3 33 | - name: 'Run Test Kitchen' 34 | run: 'bundle exec kitchen verify ${{ matrix.instance }}' 35 | -------------------------------------------------------------------------------- /.github/workflows/kitchen.windows.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | name: 'Kitchen (Windows)' 5 | 'on': ['push', 'pull_request'] 6 | 7 | env: 8 | machine_user: kitchen 9 | machine_pass: Pass@word1 10 | machine_port: 5985 11 | KITCHEN_LOCAL_YAML: 'kitchen.windows.yml' 12 | 13 | jobs: 14 | test-2022: 15 | runs-on: 'windows-2022' 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | instance: 20 | - default-windows-2022-latest-py3 21 | steps: 22 | - name: 'Check out code' 23 | uses: 'actions/checkout@v2' 24 | - name: 'Install Chef' 25 | uses: 'actionshub/chef-install@1.1.0' 26 | with: 27 | project: 'chef' 28 | version: '16.10.8' 29 | - name: 'Add Chef bindir to PATH' 30 | uses: 'myci-actions/export-env-var-powershell@1' 31 | with: 32 | name: 'PATH' 33 | value: "C:\\opscode\\chef\\bin;\ 34 | C:\\opscode\\chef\\embedded\\bin;$env:PATH" 35 | - name: 'Set up Bundler cache' 36 | uses: 'actions/cache@v1' 37 | with: 38 | path: 'vendor/bundle' 39 | key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" 40 | restore-keys: "${{ runner.os }}-gems-" 41 | - name: 'Set up test user' 42 | run: | 43 | $password = ConvertTo-SecureString $env:machine_pass -AsPlainText -Force 44 | New-LocalUser $env:machine_user -Password $password 45 | Add-LocalGroupMember -Group "Administrators" -Member $env:machine_user 46 | - name: 'Set up WinRM' 47 | run: | 48 | Set-WSManQuickConfig -Force 49 | - name: 'Run Bundler' 50 | run: | 51 | ruby --version 52 | bundle config path vendor/bundle 53 | bundle install --jobs 4 --retry 3 54 | - name: 'Run Test Kitchen' 55 | run: 'bundle exec kitchen verify ${{ matrix.instance }}' 56 | test-2019: 57 | runs-on: 'windows-2019' 58 | strategy: 59 | fail-fast: false 60 | matrix: 61 | instance: 62 | - default-windows-2019-latest-py3 63 | steps: 64 | - name: 'Check out code' 65 | uses: 'actions/checkout@v2' 66 | - name: 'Install Chef' 67 | uses: 'actionshub/chef-install@1.1.0' 68 | with: 69 | project: 'chef' 70 | version: '16.10.8' 71 | - name: 'Add Chef bindir to PATH' 72 | uses: 'myci-actions/export-env-var-powershell@1' 73 | with: 74 | name: 'PATH' 75 | value: "C:\\opscode\\chef\\bin;\ 76 | C:\\opscode\\chef\\embedded\\bin;$env:PATH" 77 | - name: 'Set up Bundler cache' 78 | uses: 'actions/cache@v1' 79 | with: 80 | path: 'vendor/bundle' 81 | key: "${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}" 82 | restore-keys: "${{ runner.os }}-gems-" 83 | - name: 'Set up test user' 84 | run: | 85 | $password = ConvertTo-SecureString $env:machine_pass -AsPlainText -Force 86 | New-LocalUser $env:machine_user -Password $password 87 | Add-LocalGroupMember -Group "Administrators" -Member $env:machine_user 88 | - name: 'Set up WinRM' 89 | run: | 90 | Set-WSManQuickConfig -Force 91 | - name: 'Run Bundler' 92 | run: | 93 | ruby --version 94 | bundle config path vendor/bundle 95 | bundle install --jobs 4 --retry 3 96 | - name: 'Run Test Kitchen' 97 | run: 'bundle exec kitchen verify ${{ matrix.instance }}' 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a packager 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .kitchen 49 | .kitchen.local.yml 50 | kitchen.local.yml 51 | junit-*.xml 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # pyenv 78 | .python-version 79 | 80 | # celery beat schedule file 81 | celerybeat-schedule 82 | 83 | # SageMath parsed files 84 | *.sage.py 85 | 86 | # dotenv 87 | .env 88 | 89 | # virtualenv 90 | .venv 91 | venv/ 92 | ENV/ 93 | 94 | # visual studio 95 | .vs/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | 101 | # Rope project settings 102 | .ropeproject 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | 110 | # Bundler 111 | .bundle/ 112 | 113 | # copied `.md` files used for conversion to `.rst` using `m2r` 114 | docs/*.md 115 | 116 | # Vim 117 | *.sw? 118 | 119 | ## Collected when centralising formulas (check and sort) 120 | # `collectd-formula` 121 | .pytest_cache/ 122 | /.idea/ 123 | Dockerfile.*_* 124 | ignore/ 125 | tmp/ 126 | 127 | # `salt-formula` -- Vagrant Specific files 128 | .vagrant 129 | top.sls 130 | !test/salt/pillar/top.sls 131 | 132 | # `suricata-formula` -- Platform binaries 133 | *.rpm 134 | *.deb 135 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | ############################################################################### 5 | # Define all YAML node anchors 6 | ############################################################################### 7 | .node_anchors: 8 | # `only` (also used for `except` where applicable) 9 | only_branch_master_parent_repo: &only_branch_master_parent_repo 10 | - 'master@saltstack-formulas/openvpn-formula' 11 | # `stage` 12 | stage_lint: &stage_lint 'lint' 13 | stage_release: &stage_release 'release' 14 | stage_test: &stage_test 'test' 15 | # `image` 16 | image_commitlint: &image_commitlint 'myii/ssf-commitlint:11' 17 | image_dindruby: &image_dindruby 'myii/ssf-dind-ruby:2.7.1-r3' 18 | image_precommit: &image_precommit 19 | name: 'myii/ssf-pre-commit:2.9.2' 20 | entrypoint: ['/bin/bash', '-c'] 21 | image_rubocop: &image_rubocop 'pipelinecomponents/rubocop:latest' 22 | image_semantic-release: &image_semanticrelease 'myii/ssf-semantic-release:15.14' 23 | # `services` 24 | services_docker_dind: &services_docker_dind 25 | - 'docker:dind' 26 | # `variables` 27 | # https://forum.gitlab.com/t/gitlab-com-ci-caching-rubygems/5627/3 28 | # https://bundler.io/v1.16/bundle_config.html 29 | variables_bundler: &variables_bundler 30 | BUNDLE_CACHE_PATH: '${CI_PROJECT_DIR}/.cache/bundler' 31 | BUNDLE_WITHOUT: 'production' 32 | # `cache` 33 | cache_bundler: &cache_bundler 34 | key: '${CI_JOB_STAGE}' 35 | paths: 36 | - '${BUNDLE_CACHE_PATH}' 37 | 38 | ############################################################################### 39 | # Define stages and global variables 40 | ############################################################################### 41 | stages: 42 | - *stage_lint 43 | - *stage_test 44 | - *stage_release 45 | variables: 46 | DOCKER_DRIVER: 'overlay2' 47 | 48 | ############################################################################### 49 | # `lint` stage: `commitlint`, `pre-commit` & `rubocop` (latest, failure allowed) 50 | ############################################################################### 51 | commitlint: 52 | stage: *stage_lint 53 | image: *image_commitlint 54 | script: 55 | # Add `upstream` remote to get access to `upstream/master` 56 | - 'git remote add upstream 57 | https://gitlab.com/saltstack-formulas/openvpn-formula.git' 58 | - 'git fetch --all' 59 | # Set default commit hashes for `--from` and `--to` 60 | - 'export COMMITLINT_FROM="$(git merge-base upstream/master HEAD)"' 61 | - 'export COMMITLINT_TO="${CI_COMMIT_SHA}"' 62 | # `coqbot` adds a merge commit to test PRs on top of the latest commit in 63 | # the repo; amend this merge commit message to avoid failure 64 | - | 65 | if [ "${GITLAB_USER_LOGIN}" = "coqbot" ] \ 66 | && [ "${CI_COMMIT_BRANCH}" != "master" ]; then 67 | git commit --amend -m \ 68 | 'chore: reword coqbot merge commit message for commitlint' 69 | export COMMITLINT_TO=HEAD 70 | fi 71 | # Run `commitlint` 72 | - 'commitlint --from "${COMMITLINT_FROM}" 73 | --to "${COMMITLINT_TO}" 74 | --verbose' 75 | 76 | pre-commit: 77 | stage: *stage_lint 78 | image: *image_precommit 79 | # https://pre-commit.com/#gitlab-ci-example 80 | variables: 81 | PRE_COMMIT_HOME: '${CI_PROJECT_DIR}/.cache/pre-commit' 82 | cache: 83 | key: '${CI_JOB_NAME}' 84 | paths: 85 | - '${PRE_COMMIT_HOME}' 86 | script: 87 | - 'pre-commit run --all-files --color always --verbose' 88 | 89 | # Use a separate job for `rubocop` other than the one potentially run by `pre-commit` 90 | # - The `pre-commit` check will only be available for formulas that pass the default 91 | # `rubocop` check -- and must continue to do so 92 | # - This job is allowed to fail, so can be used for all formulas 93 | # - Furthermore, this job uses all of the latest `rubocop` features & cops, 94 | # which will help when upgrading the `rubocop` linter used in `pre-commit` 95 | rubocop: 96 | allow_failure: true 97 | stage: *stage_lint 98 | image: *image_rubocop 99 | script: 100 | - 'rubocop -d -P -S --enable-pending-cops' 101 | 102 | ############################################################################### 103 | # Define `test` template 104 | ############################################################################### 105 | .test_instance: &test_instance 106 | stage: *stage_test 107 | image: *image_dindruby 108 | services: *services_docker_dind 109 | variables: *variables_bundler 110 | cache: *cache_bundler 111 | before_script: 112 | # TODO: This should work from the env vars above automatically 113 | - 'bundle config set path "${BUNDLE_CACHE_PATH}"' 114 | - 'bundle config set without "${BUNDLE_WITHOUT}"' 115 | - 'bundle install' 116 | script: 117 | # Alternative value to consider: `${CI_JOB_NAME}` 118 | - 'bin/kitchen verify "${DOCKER_ENV_CI_JOB_NAME}"' 119 | 120 | ############################################################################### 121 | # Define `test` template (`allow_failure: true`) 122 | ############################################################################### 123 | .test_instance_failure_permitted: 124 | <<: *test_instance 125 | allow_failure: true 126 | 127 | ############################################################################### 128 | # `test` stage: each instance below uses the `test` template above 129 | ############################################################################### 130 | ## Define the rest of the matrix based on Kitchen testing 131 | # Make sure the instances listed below match up with 132 | # the `platforms` defined in `kitchen.yml` 133 | # yamllint disable rule:line-length 134 | # default-debian-11-tiamat-py3: {extends: '.test_instance'} 135 | # default-debian-10-tiamat-py3: {extends: '.test_instance'} 136 | # default-debian-9-tiamat-py3: {extends: '.test_instance'} 137 | # default-ubuntu-2204-tiamat-py3: {extends: '.test_instance_failure_permitted'} 138 | # default-ubuntu-2004-tiamat-py3: {extends: '.test_instance'} 139 | # default-ubuntu-1804-tiamat-py3: {extends: '.test_instance'} 140 | # default-centos-stream8-tiamat-py3: {extends: '.test_instance_failure_permitted'} 141 | # default-centos-7-tiamat-py3: {extends: '.test_instance'} 142 | # default-amazonlinux-2-tiamat-py3: {extends: '.test_instance'} 143 | # default-oraclelinux-8-tiamat-py3: {extends: '.test_instance'} 144 | # default-oraclelinux-7-tiamat-py3: {extends: '.test_instance'} 145 | # default-almalinux-8-tiamat-py3: {extends: '.test_instance'} 146 | # default-rockylinux-8-tiamat-py3: {extends: '.test_instance'} 147 | default-debian-11-master-py3: {extends: '.test_instance'} 148 | default-debian-10-master-py3: {extends: '.test_instance'} 149 | default-debian-9-master-py3: {extends: '.test_instance'} 150 | default-ubuntu-2204-master-py3: {extends: '.test_instance_failure_permitted'} 151 | default-ubuntu-2004-master-py3: {extends: '.test_instance'} 152 | default-ubuntu-1804-master-py3: {extends: '.test_instance'} 153 | # default-centos-stream8-master-py3: {extends: '.test_instance_failure_permitted'} 154 | default-centos-7-master-py3: {extends: '.test_instance'} 155 | # default-fedora-36-master-py3: {extends: '.test_instance_failure_permitted'} 156 | # default-fedora-35-master-py3: {extends: '.test_instance'} 157 | default-opensuse-leap-153-master-py3: {extends: '.test_instance'} 158 | default-opensuse-tmbl-latest-master-py3: {extends: '.test_instance_failure_permitted'} 159 | default-amazonlinux-2-master-py3: {extends: '.test_instance'} 160 | # default-oraclelinux-8-master-py3: {extends: '.test_instance'} 161 | default-oraclelinux-7-master-py3: {extends: '.test_instance'} 162 | # default-arch-base-latest-master-py3: {extends: '.test_instance'} 163 | # default-gentoo-stage3-latest-master-py3: {extends: '.test_instance'} 164 | # default-gentoo-stage3-systemd-master-py3: {extends: '.test_instance'} 165 | # default-almalinux-8-master-py3: {extends: '.test_instance'} 166 | # default-rockylinux-8-master-py3: {extends: '.test_instance'} 167 | # default-debian-11-3004-1-py3: {extends: '.test_instance'} 168 | # default-debian-10-3004-1-py3: {extends: '.test_instance'} 169 | # default-debian-9-3004-1-py3: {extends: '.test_instance'} 170 | # default-ubuntu-2204-3004-1-py3: {extends: '.test_instance_failure_permitted'} 171 | # default-ubuntu-2004-3004-1-py3: {extends: '.test_instance'} 172 | # default-ubuntu-1804-3004-1-py3: {extends: '.test_instance'} 173 | # default-centos-stream8-3004-1-py3: {extends: '.test_instance_failure_permitted'} 174 | # default-centos-7-3004-1-py3: {extends: '.test_instance'} 175 | # default-fedora-36-3004-1-py3: {extends: '.test_instance_failure_permitted'} 176 | # default-fedora-35-3004-1-py3: {extends: '.test_instance'} 177 | # default-amazonlinux-2-3004-1-py3: {extends: '.test_instance'} 178 | # default-oraclelinux-8-3004-1-py3: {extends: '.test_instance'} 179 | # default-oraclelinux-7-3004-1-py3: {extends: '.test_instance'} 180 | # default-arch-base-latest-3004-1-py3: {extends: '.test_instance'} 181 | # default-gentoo-stage3-latest-3004-1-py3: {extends: '.test_instance'} 182 | # default-gentoo-stage3-systemd-3004-1-py3: {extends: '.test_instance'} 183 | # default-almalinux-8-3004-1-py3: {extends: '.test_instance'} 184 | # default-rockylinux-8-3004-1-py3: {extends: '.test_instance'} 185 | # default-opensuse-leap-153-3004-0-py3: {extends: '.test_instance'} 186 | # default-opensuse-tmbl-latest-3004-0-py3: {extends: '.test_instance_failure_permitted'} 187 | # default-debian-10-3003-4-py3: {extends: '.test_instance'} 188 | # default-debian-9-3003-4-py3: {extends: '.test_instance'} 189 | # default-ubuntu-2004-3003-4-py3: {extends: '.test_instance'} 190 | # default-ubuntu-1804-3003-4-py3: {extends: '.test_instance'} 191 | # default-centos-stream8-3003-4-py3: {extends: '.test_instance_failure_permitted'} 192 | # default-centos-7-3003-4-py3: {extends: '.test_instance'} 193 | # default-amazonlinux-2-3003-4-py3: {extends: '.test_instance'} 194 | # default-oraclelinux-8-3003-4-py3: {extends: '.test_instance'} 195 | # default-oraclelinux-7-3003-4-py3: {extends: '.test_instance'} 196 | # default-almalinux-8-3003-4-py3: {extends: '.test_instance'} 197 | # yamllint enable rule:line-length 198 | 199 | ############################################################################### 200 | # `release` stage: `semantic-release` 201 | ############################################################################### 202 | semantic-release: 203 | only: *only_branch_master_parent_repo 204 | stage: *stage_release 205 | image: *image_semanticrelease 206 | variables: 207 | MAINTAINER_TOKEN: '${GH_TOKEN}' 208 | script: 209 | # Update `AUTHORS.md` 210 | - '${HOME}/go/bin/maintainer contributor' 211 | # Run `semantic-release` 212 | - 'semantic-release' 213 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | # See https://pre-commit.com for more information 5 | # See https://pre-commit.com/hooks.html for more hooks 6 | ci: 7 | autofix_commit_msg: | 8 | ci(pre-commit.ci): apply auto fixes from pre-commit.com hooks 9 | 10 | For more information, see https://pre-commit.ci 11 | autofix_prs: true 12 | autoupdate_branch: '' 13 | autoupdate_commit_msg: | 14 | ci(pre-commit.ci): perform `pre-commit` autoupdate 15 | autoupdate_schedule: quarterly 16 | skip: [] 17 | submodules: false 18 | default_stages: [commit] 19 | repos: 20 | - repo: https://github.com/dafyddj/commitlint-pre-commit-hook 21 | rev: v2.3.0 22 | hooks: 23 | - id: commitlint 24 | name: Check commit message using commitlint 25 | description: Lint commit message against @commitlint/config-conventional rules 26 | stages: [commit-msg] 27 | additional_dependencies: ['@commitlint/config-conventional@8.3.4'] 28 | - id: commitlint-travis 29 | stages: [manual] 30 | additional_dependencies: ['@commitlint/config-conventional@8.3.4'] 31 | always_run: true 32 | - repo: https://github.com/rubocop-hq/rubocop 33 | rev: v1.30.1 34 | hooks: 35 | - id: rubocop 36 | name: Check Ruby files with rubocop 37 | args: [--debug] 38 | always_run: true 39 | pass_filenames: false 40 | - repo: https://github.com/shellcheck-py/shellcheck-py 41 | rev: v0.8.0.4 42 | hooks: 43 | - id: shellcheck 44 | name: Check shell scripts with shellcheck 45 | files: ^.*\.(sh|bash|ksh)$ 46 | types: [] 47 | - repo: https://github.com/adrienverge/yamllint 48 | rev: v1.26.3 49 | hooks: 50 | - id: yamllint 51 | name: Check YAML syntax with yamllint 52 | args: [--strict, '.'] 53 | always_run: true 54 | pass_filenames: false 55 | - repo: https://github.com/warpnet/salt-lint 56 | rev: v0.8.0 57 | hooks: 58 | - id: salt-lint 59 | name: Check Salt files using salt-lint 60 | files: ^.*\.(sls|jinja|j2|tmpl|tst)$ 61 | - repo: https://github.com/myint/rstcheck 62 | rev: 3f929574 63 | hooks: 64 | - id: rstcheck 65 | name: Check reST files using rstcheck 66 | exclude: 'docs/CHANGELOG.rst' 67 | - repo: https://github.com/saltstack-formulas/mirrors-rst-lint 68 | rev: v1.3.2 69 | hooks: 70 | - id: rst-lint 71 | name: Check reST files using rst-lint 72 | exclude: | 73 | (?x)^( 74 | docs/CHANGELOG.rst| 75 | docs/TOFS_pattern.rst| 76 | )$ 77 | additional_dependencies: [pygments==2.9.0] 78 | -------------------------------------------------------------------------------- /.rstcheck.cfg: -------------------------------------------------------------------------------- 1 | [rstcheck] 2 | report=info 3 | ignore_language=rst 4 | ignore_messages=(Duplicate (ex|im)plicit target.*|Hyperlink target ".*" is not referenced\.$) 5 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | # General overrides used across formulas in the org 5 | Layout/LineLength: 6 | # Increase from default of `80` 7 | # Based on https://github.com/PyCQA/flake8-bugbear#opinionated-warnings (`B950`) 8 | Max: 88 9 | Metrics/BlockLength: 10 | IgnoredMethods: 11 | - control 12 | - describe 13 | # Increase from default of `25` 14 | Max: 30 15 | Security/YAMLLoad: 16 | Exclude: 17 | - test/integration/**/_mapdata.rb 18 | 19 | # General settings across all cops in this formula 20 | AllCops: 21 | NewCops: enable 22 | 23 | # Any offenses that should be fixed, e.g. collected via. `rubocop --auto-gen-config` 24 | -------------------------------------------------------------------------------- /.salt-lint: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | exclude_paths: [] 5 | rules: {} 6 | skip_list: 7 | # Using `salt-lint` for linting other files as well, such as Jinja macros/templates 8 | - 205 # Use ".sls" as a Salt State file extension 9 | # Skipping `207` and `208` because `210` is sufficient, at least for the time-being 10 | # I.e. Allows 3-digit unquoted codes to still be used, such as `644` and `755` 11 | - 207 # File modes should always be encapsulated in quotation marks 12 | - 208 # File modes should always contain a leading zero 13 | tags: [] 14 | verbosity: 1 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | ################################################################################ 5 | # NOTE: This file is UNMAINTAINED; it is provided for references purposes only. 6 | # No guarantees are tendered that this structure will work after 2020. 7 | ################################################################################ 8 | # * https://en.wikipedia.org/wiki/Travis_CI: 9 | # - "... free open-source plans were removed in [sic] the end of 2020" 10 | # - https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing 11 | # - https://ropensci.org/technotes/2020/11/19/moving-away-travis/ 12 | ################################################################################ 13 | ## Machine config 14 | os: 'linux' 15 | arch: 'amd64' 16 | dist: 'bionic' 17 | version: '~> 1.0' 18 | 19 | ## Language and cache config 20 | language: 'ruby' 21 | cache: 'bundler' 22 | 23 | ## Services config 24 | services: 25 | - docker 26 | 27 | ## Script to run for the test stage 28 | script: 29 | - bin/kitchen verify "${INSTANCE}" 30 | 31 | ## Stages and jobs matrix 32 | stages: 33 | - test 34 | # # As part of the switch away from Travis CI, ensure that the `release` stage 35 | # # is not run inadvertently 36 | # - name: 'release' 37 | # if: 'branch = master AND type != pull_request' 38 | jobs: 39 | include: 40 | ## Define the test stage that runs the linters (and testing matrix, if applicable) 41 | 42 | # Run all of the linters in a single job 43 | - language: 'node_js' 44 | node_js: 'lts/*' 45 | env: 'Lint' 46 | name: 'Lint: salt-lint, yamllint, rubocop, shellcheck & commitlint' 47 | before_install: 'skip' 48 | script: 49 | # Install and run `salt-lint` 50 | - pip install --user salt-lint 51 | - git ls-files -- '*.sls' '*.jinja' '*.j2' '*.tmpl' '*.tst' 52 | | xargs salt-lint 53 | # Install and run `yamllint` 54 | # Need at least `v1.17.0` for the `yaml-files` setting 55 | - pip install --user yamllint>=1.17.0 56 | - yamllint -s . 57 | # Install and run `rubocop` 58 | - gem install rubocop 59 | - rubocop -d 60 | # Run `shellcheck` (already pre-installed in Travis) 61 | - shellcheck --version 62 | - git ls-files -- '*.sh' '*.bash' '*.ksh' 63 | | xargs shellcheck 64 | # Install and run `commitlint` 65 | - npm i -D @commitlint/config-conventional 66 | @commitlint/travis-cli 67 | - commitlint-travis 68 | 69 | # Run `pre-commit` linters in a single job 70 | - language: 'python' 71 | env: 'Lint_pre-commit' 72 | name: 'Lint: pre-commit' 73 | before_install: 'skip' 74 | cache: 75 | directories: 76 | - $HOME/.cache/pre-commit 77 | script: 78 | # Install and run `pre-commit` 79 | - pip install pre-commit==2.7.1 80 | - pre-commit run --all-files --color always --verbose 81 | - pre-commit run --color always --hook-stage manual --verbose commitlint-travis 82 | 83 | ## Define the rest of the matrix based on Kitchen testing 84 | # Make sure the instances listed below match up with 85 | # the `platforms` defined in `kitchen.yml` 86 | # - env: INSTANCE=default-debian-11-tiamat-py3 87 | # - env: INSTANCE=default-debian-10-tiamat-py3 88 | # - env: INSTANCE=default-debian-9-tiamat-py3 89 | # - env: INSTANCE=default-ubuntu-2204-tiamat-py3 90 | # - env: INSTANCE=default-ubuntu-2004-tiamat-py3 91 | # - env: INSTANCE=default-ubuntu-1804-tiamat-py3 92 | # - env: INSTANCE=default-centos-stream8-tiamat-py3 93 | # - env: INSTANCE=default-centos-7-tiamat-py3 94 | # - env: INSTANCE=default-amazonlinux-2-tiamat-py3 95 | # - env: INSTANCE=default-oraclelinux-8-tiamat-py3 96 | # - env: INSTANCE=default-oraclelinux-7-tiamat-py3 97 | # - env: INSTANCE=default-almalinux-8-tiamat-py3 98 | # - env: INSTANCE=default-rockylinux-8-tiamat-py3 99 | - env: INSTANCE=default-debian-11-master-py3 100 | - env: INSTANCE=default-debian-10-master-py3 101 | - env: INSTANCE=default-debian-9-master-py3 102 | - env: INSTANCE=default-ubuntu-2204-master-py3 103 | - env: INSTANCE=default-ubuntu-2004-master-py3 104 | - env: INSTANCE=default-ubuntu-1804-master-py3 105 | # - env: INSTANCE=default-centos-stream8-master-py3 106 | - env: INSTANCE=default-centos-7-master-py3 107 | # - env: INSTANCE=default-fedora-36-master-py3 108 | # - env: INSTANCE=default-fedora-35-master-py3 109 | - env: INSTANCE=default-opensuse-leap-153-master-py3 110 | - env: INSTANCE=default-opensuse-tmbl-latest-master-py3 111 | - env: INSTANCE=default-amazonlinux-2-master-py3 112 | # - env: INSTANCE=default-oraclelinux-8-master-py3 113 | - env: INSTANCE=default-oraclelinux-7-master-py3 114 | # - env: INSTANCE=default-arch-base-latest-master-py3 115 | # - env: INSTANCE=default-gentoo-stage3-latest-master-py3 116 | # - env: INSTANCE=default-gentoo-stage3-systemd-master-py3 117 | # - env: INSTANCE=default-almalinux-8-master-py3 118 | # - env: INSTANCE=default-rockylinux-8-master-py3 119 | # - env: INSTANCE=default-debian-11-3004-1-py3 120 | # - env: INSTANCE=default-debian-10-3004-1-py3 121 | # - env: INSTANCE=default-debian-9-3004-1-py3 122 | # - env: INSTANCE=default-ubuntu-2204-3004-1-py3 123 | # - env: INSTANCE=default-ubuntu-2004-3004-1-py3 124 | # - env: INSTANCE=default-ubuntu-1804-3004-1-py3 125 | # - env: INSTANCE=default-centos-stream8-3004-1-py3 126 | # - env: INSTANCE=default-centos-7-3004-1-py3 127 | # - env: INSTANCE=default-fedora-36-3004-1-py3 128 | # - env: INSTANCE=default-fedora-35-3004-1-py3 129 | # - env: INSTANCE=default-amazonlinux-2-3004-1-py3 130 | # - env: INSTANCE=default-oraclelinux-8-3004-1-py3 131 | # - env: INSTANCE=default-oraclelinux-7-3004-1-py3 132 | # - env: INSTANCE=default-arch-base-latest-3004-1-py3 133 | # - env: INSTANCE=default-gentoo-stage3-latest-3004-1-py3 134 | # - env: INSTANCE=default-gentoo-stage3-systemd-3004-1-py3 135 | # - env: INSTANCE=default-almalinux-8-3004-1-py3 136 | # - env: INSTANCE=default-rockylinux-8-3004-1-py3 137 | # - env: INSTANCE=default-opensuse-leap-153-3004-0-py3 138 | # - env: INSTANCE=default-opensuse-tmbl-latest-3004-0-py3 139 | # - env: INSTANCE=default-debian-10-3003-4-py3 140 | # - env: INSTANCE=default-debian-9-3003-4-py3 141 | # - env: INSTANCE=default-ubuntu-2004-3003-4-py3 142 | # - env: INSTANCE=default-ubuntu-1804-3003-4-py3 143 | # - env: INSTANCE=default-centos-stream8-3003-4-py3 144 | # - env: INSTANCE=default-centos-7-3003-4-py3 145 | # - env: INSTANCE=default-amazonlinux-2-3003-4-py3 146 | # - env: INSTANCE=default-oraclelinux-8-3003-4-py3 147 | # - env: INSTANCE=default-oraclelinux-7-3003-4-py3 148 | # - env: INSTANCE=default-almalinux-8-3003-4-py3 149 | 150 | ## Define the release stage that runs `semantic-release` 151 | - stage: 'release' 152 | language: 'node_js' 153 | node_js: 'lts/*' 154 | env: 'Release' 155 | name: 'Run semantic-release inc. file updates to AUTHORS, CHANGELOG & FORMULA' 156 | before_install: 'skip' 157 | script: 158 | # Update `AUTHORS.md` 159 | - export MAINTAINER_TOKEN=${GH_TOKEN} 160 | - go get github.com/myii/maintainer 161 | - maintainer contributor 162 | 163 | # Install all dependencies required for `semantic-release` 164 | - npm i -D @semantic-release/changelog@3 165 | @semantic-release/exec@3 166 | @semantic-release/git@7 167 | deploy: 168 | provider: 'script' 169 | # Opt-in to `dpl v2` to complete the Travis build config validation (beta) 170 | # * https://docs.travis-ci.com/user/build-config-validation 171 | # Deprecated `skip_cleanup` can now be avoided, `cleanup: false` is by default 172 | edge: true 173 | # Run `semantic-release` 174 | script: 'npx semantic-release@15.14' 175 | 176 | # Notification options: `always`, `never` or `change` 177 | notifications: 178 | webhooks: 179 | if: 'repo = saltstack-formulas/openvpn-formula' 180 | urls: 181 | - https://saltstack-formulas.zulipchat.com/api/v1/external/travis?api_key=HsIq3o5QmLxdnVCKF9is0FUIpkpAY79P&stream=CI&topic=saltstack-formulas%2Fopenvpn-formula&ignore_pull_requests=true 182 | on_success: always # default: always 183 | on_failure: always # default: always 184 | on_start: always # default: never 185 | on_cancel: always # default: always 186 | on_error: always # default: always 187 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | # Extend the `default` configuration provided by `yamllint` 5 | extends: 'default' 6 | 7 | # Files to ignore completely 8 | # 1. All YAML files under directory `.bundle/`, introduced if gems are installed locally 9 | # 2. All YAML files under directory `.cache/`, introduced during the CI run 10 | # 3. All YAML files under directory `.git/` 11 | # 4. All YAML files under directory `node_modules/`, introduced during the CI run 12 | # 5. Any SLS files under directory `test/`, which are actually state files 13 | # 6. Any YAML files under directory `.kitchen/`, introduced during local testing 14 | # 7. `kitchen.vagrant.yml`, which contains Embedded Ruby (ERB) template syntax 15 | ignore: | 16 | .bundle/ 17 | .cache/ 18 | .git/ 19 | node_modules/ 20 | test/**/states/**/*.sls 21 | .kitchen/ 22 | kitchen.vagrant.yml 23 | test/salt/pillar/default.sls 24 | 25 | yaml-files: 26 | # Default settings 27 | - '*.yaml' 28 | - '*.yml' 29 | - .salt-lint 30 | - .yamllint 31 | # SaltStack Formulas additional settings 32 | - '*.example' 33 | - test/**/*.sls 34 | 35 | rules: 36 | empty-values: 37 | forbid-in-block-mappings: true 38 | forbid-in-flow-mappings: true 39 | line-length: 40 | # Increase from default of `80` 41 | # Based on https://github.com/PyCQA/flake8-bugbear#opinionated-warnings (`B950`) 42 | max: 88 43 | octal-values: 44 | forbid-implicit-octal: true 45 | forbid-explicit-octal: true 46 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Authors 2 | 3 | This list is sorted by the number of commits per contributor in _descending_ order. 4 | 5 | Avatar|Contributor|Contributions 6 | :-:|---|:-: 7 | @myii|[@myii](https://github.com/myii)|177 8 | @alxwr|[@alxwr](https://github.com/alxwr)|96 9 | @dafyddj|[@dafyddj](https://github.com/dafyddj)|61 10 | @TimJones|[@TimJones](https://github.com/TimJones)|21 11 | @aboe76|[@aboe76](https://github.com/aboe76)|19 12 | @puneetk|[@puneetk](https://github.com/puneetk)|12 13 | @daschatten|[@daschatten](https://github.com/daschatten)|11 14 | @marconett|[@marconett](https://github.com/marconett)|9 15 | @sc250024|[@sc250024](https://github.com/sc250024)|6 16 | @baby-gnu|[@baby-gnu](https://github.com/baby-gnu)|6 17 | @wolodjawentland|[@wolodjawentland](https://github.com/wolodjawentland)|5 18 | @diegofd|[@diegofd](https://github.com/diegofd)|4 19 | @javierbertoli|[@javierbertoli](https://github.com/javierbertoli)|4 20 | @landergate|[@landergate](https://github.com/landergate)|4 21 | @aviau|[@aviau](https://github.com/aviau)|3 22 | @nmadhok|[@nmadhok](https://github.com/nmadhok)|3 23 | @viper233|[@viper233](https://github.com/viper233)|3 24 | @timwhite|[@timwhite](https://github.com/timwhite)|3 25 | @daks|[@daks](https://github.com/daks)|3 26 | @alexhayes|[@alexhayes](https://github.com/alexhayes)|2 27 | @iggy|[@iggy](https://github.com/iggy)|2 28 | @dimitry-unified-streaming|[@dimitry-unified-streaming](https://github.com/dimitry-unified-streaming)|2 29 | @t0fik|[@t0fik](https://github.com/t0fik)|2 30 | @anderbubble|[@anderbubble](https://github.com/anderbubble)|2 31 | @kevinschmidt|[@kevinschmidt](https://github.com/kevinschmidt)|2 32 | @Wenzel|[@Wenzel](https://github.com/Wenzel)|2 33 | @stasjok|[@stasjok](https://github.com/stasjok)|2 34 | @genuss|[@genuss](https://github.com/genuss)|2 35 | @cmclaughlin|[@cmclaughlin](https://github.com/cmclaughlin)|2 36 | @noelmcloughlin|[@noelmcloughlin](https://github.com/noelmcloughlin)|2 37 | @aldovillagra|[@aldovillagra](https://github.com/aldovillagra)|1 38 | @blbradley|[@blbradley](https://github.com/blbradley)|1 39 | @vielmetti|[@vielmetti](https://github.com/vielmetti)|1 40 | @gboddin|[@gboddin](https://github.com/gboddin)|1 41 | @icflournoy|[@icflournoy](https://github.com/icflournoy)|1 42 | @mthibaut|[@mthibaut](https://github.com/mthibaut)|1 43 | @marek-knappe|[@marek-knappe](https://github.com/marek-knappe)|1 44 | @oselivanov|[@oselivanov](https://github.com/oselivanov)|1 45 | @kevit|[@kevit](https://github.com/kevit)|1 46 | @tobio|[@tobio](https://github.com/tobio)|1 47 | 48 | --- 49 | 50 | Auto-generated by a [forked version](https://github.com/myii/maintainer) of [gaocegege/maintainer](https://github.com/gaocegege/maintainer) on 2022-08-16. 51 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 2 | 3 | # SECTION: Owner(s) for everything in the repo, unless a later match takes precedence 4 | # FILE PATTERN OWNER(S) 5 | * @dafyddj 6 | 7 | # SECTION: Owner(s) for specific directories 8 | # FILE PATTERN OWNER(S) 9 | 10 | # SECTION: Owner(s) for files/directories related to `semantic-release` 11 | # FILE PATTERN OWNER(S) 12 | /.github/workflows/ @saltstack-formulas/ssf 13 | /bin/install-hooks @saltstack-formulas/ssf 14 | /bin/kitchen @saltstack-formulas/ssf 15 | /docs/AUTHORS.rst @saltstack-formulas/ssf 16 | /docs/CHANGELOG.rst @saltstack-formulas/ssf 17 | /docs/TOFS_pattern.rst @saltstack-formulas/ssf 18 | /*/_mapdata/ @saltstack-formulas/ssf 19 | /*/libmapstack.jinja @saltstack-formulas/ssf 20 | /*/libmatchers.jinja @saltstack-formulas/ssf 21 | /*/libsaltcli.jinja @saltstack-formulas/ssf 22 | /*/libtofs.jinja @saltstack-formulas/ssf 23 | /*/map.jinja @saltstack-formulas/ssf 24 | /test/integration/**/_mapdata.rb @saltstack-formulas/ssf 25 | /test/integration/**/libraries/system.rb @saltstack-formulas/ssf 26 | /test/integration/**/inspec.yml @saltstack-formulas/ssf 27 | /test/integration/**/README.md @saltstack-formulas/ssf 28 | /test/salt/pillar/top.sls @saltstack-formulas/ssf 29 | /.gitignore @saltstack-formulas/ssf 30 | /.cirrus.yml @saltstack-formulas/ssf 31 | /.gitlab-ci.yml @saltstack-formulas/ssf 32 | /.pre-commit-config.yaml @saltstack-formulas/ssf 33 | /.rstcheck.cfg @saltstack-formulas/ssf 34 | /.rubocop.yml @saltstack-formulas/ssf 35 | /.salt-lint @saltstack-formulas/ssf 36 | /.travis.yml @saltstack-formulas/ssf 37 | /.yamllint @saltstack-formulas/ssf 38 | /AUTHORS.md @saltstack-formulas/ssf 39 | /CHANGELOG.md @saltstack-formulas/ssf 40 | /CODEOWNERS @saltstack-formulas/ssf 41 | /commitlint.config.js @saltstack-formulas/ssf 42 | /FORMULA @saltstack-formulas/ssf 43 | /Gemfile @saltstack-formulas/ssf 44 | /Gemfile.lock @saltstack-formulas/ssf 45 | /kitchen.yml @saltstack-formulas/ssf 46 | /kitchen.vagrant.yml @saltstack-formulas/ssf 47 | /kitchen.windows.yml @saltstack-formulas/ssf 48 | /pre-commit_semantic-release.sh @saltstack-formulas/ssf 49 | /release-rules.js @saltstack-formulas/ssf 50 | /release.config.js @saltstack-formulas/ssf 51 | 52 | # SECTION: Owner(s) for specific files 53 | # FILE PATTERN OWNER(S) 54 | -------------------------------------------------------------------------------- /FORMULA: -------------------------------------------------------------------------------- 1 | name: template 2 | os: Debian, Ubuntu, Raspbian, RedHat, Fedora, CentOS, Suse, openSUSE, Gentoo, Funtoo, Arch, Manjaro, Alpine, FreeBSD, OpenBSD, Solaris, SmartOS, Windows, MacOS 3 | os_family: Debian, RedHat, Suse, Gentoo, Arch, Alpine, FreeBSD, OpenBSD, Solaris, Windows, MacOS 4 | version: 1.0.5 5 | release: 1 6 | minimum_version: 2018.3 7 | summary: OpenVPN formula 8 | description: Formula to use manage OpenVPN 9 | top_level_dir: openvpn 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source ENV.fetch('PROXY_RUBYGEMSORG', 'https://rubygems.org') 4 | 5 | # Install the `inspec` gem using `git` because versions after `4.22.22` 6 | # suppress diff output; this version fixes this for our uses. 7 | # rubocop:disable Layout/LineLength 8 | gem 'inspec', git: 'https://gitlab.com/saltstack-formulas/infrastructure/inspec', branch: 'ssf' 9 | # rubocop:enable Layout/LineLength 10 | 11 | # Install the `kitchen-docker` gem using `git` in order to gain a performance 12 | # improvement: avoid package installations which are already covered by the 13 | # `salt-image-builder` (i.e. the pre-salted images that we're using) 14 | # rubocop:disable Layout/LineLength 15 | gem 'kitchen-docker', git: 'https://gitlab.com/saltstack-formulas/infrastructure/kitchen-docker', branch: 'ssf' 16 | # rubocop:enable Layout/LineLength 17 | 18 | gem 'kitchen-inspec', '>= 2.5.0' 19 | gem 'kitchen-salt', '>= 0.7.2' 20 | gem 'rspec-retry' 21 | 22 | group :vagrant do 23 | gem 'kitchen-vagrant' 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2017 Salt Stack Formulas 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /bin/install-hooks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -o nounset # Treat unset variables as an error and immediately exit 3 | set -o errexit # If a command fails exit the whole script 4 | 5 | if [ "${DEBUG:-false}" = "true" ]; then 6 | set -x # Run the entire script in debug mode 7 | fi 8 | 9 | if ! command -v pre-commit >/dev/null 2>&1; then 10 | echo "pre-commit not found: please install or check your PATH" >&2 11 | echo "See https://pre-commit.com/#installation" >&2 12 | exit 1 13 | fi 14 | 15 | pre-commit install --install-hooks 16 | pre-commit install --hook-type commit-msg --install-hooks 17 | -------------------------------------------------------------------------------- /bin/kitchen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kitchen' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort( 22 | 'Your `bin/bundle` was not generated by Bundler, ' \ 23 | 'so this binstub cannot run. Replace `bin/bundle` by running ' \ 24 | '`bundle binstubs bundler --force`, then run this command again.' 25 | ) 26 | end 27 | end 28 | 29 | require 'rubygems' 30 | require 'bundler/setup' 31 | 32 | load Gem.bin_path('test-kitchen', 'kitchen') 33 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'body-max-line-length': [2, 'always', 120], 5 | 'footer-max-line-length': [2, 'always', 120], 6 | 'header-max-length': [2, 'always', 72], 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /docs/AUTHORS.rst: -------------------------------------------------------------------------------- 1 | .. role:: raw-html-m2r(raw) 2 | :format: html 3 | 4 | 5 | Authors 6 | ======= 7 | 8 | This list is sorted by the number of commits per contributor in *descending* order. 9 | 10 | .. list-table:: 11 | :header-rows: 1 12 | 13 | * - Avatar 14 | - Contributor 15 | - Contributions 16 | * - :raw-html-m2r:`@myii` 17 | - `@myii `_ 18 | - 177 19 | * - :raw-html-m2r:`@alxwr` 20 | - `@alxwr `_ 21 | - 96 22 | * - :raw-html-m2r:`@dafyddj` 23 | - `@dafyddj `_ 24 | - 61 25 | * - :raw-html-m2r:`@TimJones` 26 | - `@TimJones `_ 27 | - 21 28 | * - :raw-html-m2r:`@aboe76` 29 | - `@aboe76 `_ 30 | - 19 31 | * - :raw-html-m2r:`@puneetk` 32 | - `@puneetk `_ 33 | - 12 34 | * - :raw-html-m2r:`@daschatten` 35 | - `@daschatten `_ 36 | - 11 37 | * - :raw-html-m2r:`@marconett` 38 | - `@marconett `_ 39 | - 9 40 | * - :raw-html-m2r:`@sc250024` 41 | - `@sc250024 `_ 42 | - 6 43 | * - :raw-html-m2r:`@baby-gnu` 44 | - `@baby-gnu `_ 45 | - 6 46 | * - :raw-html-m2r:`@wolodjawentland` 47 | - `@wolodjawentland `_ 48 | - 5 49 | * - :raw-html-m2r:`@diegofd` 50 | - `@diegofd `_ 51 | - 4 52 | * - :raw-html-m2r:`@javierbertoli` 53 | - `@javierbertoli `_ 54 | - 4 55 | * - :raw-html-m2r:`@landergate` 56 | - `@landergate `_ 57 | - 4 58 | * - :raw-html-m2r:`@aviau` 59 | - `@aviau `_ 60 | - 3 61 | * - :raw-html-m2r:`@nmadhok` 62 | - `@nmadhok `_ 63 | - 3 64 | * - :raw-html-m2r:`@viper233` 65 | - `@viper233 `_ 66 | - 3 67 | * - :raw-html-m2r:`@timwhite` 68 | - `@timwhite `_ 69 | - 3 70 | * - :raw-html-m2r:`@daks` 71 | - `@daks `_ 72 | - 3 73 | * - :raw-html-m2r:`@alexhayes` 74 | - `@alexhayes `_ 75 | - 2 76 | * - :raw-html-m2r:`@iggy` 77 | - `@iggy `_ 78 | - 2 79 | * - :raw-html-m2r:`@dimitry-unified-streaming` 80 | - `@dimitry-unified-streaming `_ 81 | - 2 82 | * - :raw-html-m2r:`@t0fik` 83 | - `@t0fik `_ 84 | - 2 85 | * - :raw-html-m2r:`@anderbubble` 86 | - `@anderbubble `_ 87 | - 2 88 | * - :raw-html-m2r:`@kevinschmidt` 89 | - `@kevinschmidt `_ 90 | - 2 91 | * - :raw-html-m2r:`@Wenzel` 92 | - `@Wenzel `_ 93 | - 2 94 | * - :raw-html-m2r:`@stasjok` 95 | - `@stasjok `_ 96 | - 2 97 | * - :raw-html-m2r:`@genuss` 98 | - `@genuss `_ 99 | - 2 100 | * - :raw-html-m2r:`@cmclaughlin` 101 | - `@cmclaughlin `_ 102 | - 2 103 | * - :raw-html-m2r:`@noelmcloughlin` 104 | - `@noelmcloughlin `_ 105 | - 2 106 | * - :raw-html-m2r:`@aldovillagra` 107 | - `@aldovillagra `_ 108 | - 1 109 | * - :raw-html-m2r:`@blbradley` 110 | - `@blbradley `_ 111 | - 1 112 | * - :raw-html-m2r:`@vielmetti` 113 | - `@vielmetti `_ 114 | - 1 115 | * - :raw-html-m2r:`@gboddin` 116 | - `@gboddin `_ 117 | - 1 118 | * - :raw-html-m2r:`@icflournoy` 119 | - `@icflournoy `_ 120 | - 1 121 | * - :raw-html-m2r:`@mthibaut` 122 | - `@mthibaut `_ 123 | - 1 124 | * - :raw-html-m2r:`@marek-knappe` 125 | - `@marek-knappe `_ 126 | - 1 127 | * - :raw-html-m2r:`@oselivanov` 128 | - `@oselivanov `_ 129 | - 1 130 | * - :raw-html-m2r:`@kevit` 131 | - `@kevit `_ 132 | - 1 133 | * - :raw-html-m2r:`@tobio` 134 | - `@tobio `_ 135 | - 1 136 | 137 | 138 | ---- 139 | 140 | Auto-generated by a `forked version `_ of `gaocegege/maintainer `_ on 2022-08-16. 141 | -------------------------------------------------------------------------------- /docs/README.rst: -------------------------------------------------------------------------------- 1 | openvpn-formula 2 | =============== 3 | 4 | 5 | |img_travis| |img_sr| 6 | 7 | .. |img_travis| image:: https://travis-ci.com/saltstack-formulas/openvpn-formula.svg?branch=master 8 | :alt: Travis CI Build Status 9 | :scale: 100% 10 | :target: https://travis-ci.com/saltstack-formulas/openvpn-formula 11 | .. |img_sr| image:: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 12 | :alt: Semantic Release 13 | :scale: 100% 14 | :target: https://github.com/semantic-release/semantic-release 15 | 16 | Formula to install and configure openvpn server and client. 17 | 18 | .. contents:: **Table of Contents** 19 | 20 | General notes 21 | ------------- 22 | 23 | See the full `SaltStack Formulas installation and usage instructions 24 | `_. 25 | 26 | If you are interested in writing or contributing to formulas, please pay attention to the `Writing Formula Section 27 | `_. 28 | 29 | If you want to use this formula, please pay attention to the ``FORMULA`` file and/or ``git tag``, 30 | which contains the currently released version. This formula is versioned according to `Semantic Versioning `_. 31 | 32 | See `Formula Versioning Section `_ for more details. 33 | 34 | If you need (non-default) configuration, please refer to: 35 | 36 | - `how to configure the formula with map.jinja `_ 37 | - the ``pillar.example`` file 38 | 39 | 40 | Contributing to this repo 41 | ------------------------- 42 | 43 | **Commit message formatting is significant!!** 44 | 45 | Please see `How to contribute `_ for more details. 46 | 47 | 48 | Available states 49 | ---------------- 50 | 51 | .. contents:: 52 | :local: 53 | 54 | ``openvpn`` 55 | ^^^^^^^^^^^ 56 | 57 | Installs OpenVPN. 58 | 59 | ``openvpn.config`` 60 | ^^^^^^^^^^^^^^^^^^ 61 | 62 | Configures OpenVPN client and server. Multiple clients and servers are possible. 63 | 64 | ``openvpn.gui`` 65 | ^^^^^^^^^^^^^^^ 66 | 67 | Configures OpenVPN GUI (Windows only). Sets global registry settings as described `here `_. 68 | 69 | ``openvpn.adapters`` 70 | ^^^^^^^^^^^^^^^^^^^^ 71 | 72 | Manages TAP-Windows device adapters (Windows only). Ensures that any devices specified with ``dev_node`` in pillar exist. 73 | 74 | ``openvpn.ifconfig_pool_persist`` 75 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 76 | 77 | Installs and configures an ifconfig_pool_persist file. Used to assign host IPs. 78 | 79 | ``openvpn.network_manager_networks`` 80 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 81 | 82 | Don't setup a OpenVPN client service, but add ready-to-use NetworkManager configurations. 83 | 84 | Examples 85 | -------- 86 | 87 | See *openvpn/pillar.example*. 88 | 89 | Notes 90 | ----- 91 | 92 | This formula does can optionally deploy certificates and keys, but does not generate them. This must be done manually or with another formula. 93 | 94 | Testing 95 | ------- 96 | 97 | Linux testing is done with ``kitchen-salt``. 98 | 99 | Requirements 100 | ^^^^^^^^^^^^ 101 | 102 | * Ruby 103 | * Docker 104 | 105 | .. code-block:: bash 106 | 107 | $ gem install bundler 108 | $ bundle install 109 | $ bin/kitchen test [platform] 110 | 111 | Where ``[platform]`` is the platform name defined in ``kitchen.yml``, 112 | e.g. ``debian-9-2019-2-py3``. 113 | 114 | ``bin/kitchen converge`` 115 | ^^^^^^^^^^^^^^^^^^^^^^^^ 116 | 117 | Creates the docker instance and runs the ``openvpn`` main state, ready for testing. 118 | 119 | ``bin/kitchen verify`` 120 | ^^^^^^^^^^^^^^^^^^^^^^ 121 | 122 | Runs the ``inspec`` tests on the actual instance. 123 | 124 | ``bin/kitchen destroy`` 125 | ^^^^^^^^^^^^^^^^^^^^^^^ 126 | 127 | Removes the docker instance. 128 | 129 | ``bin/kitchen test`` 130 | ^^^^^^^^^^^^^^^^^^^^ 131 | 132 | Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``verify`` + ``destroy``. 133 | 134 | ``bin/kitchen login`` 135 | ^^^^^^^^^^^^^^^^^^^^^ 136 | 137 | Gives you SSH access to the instance for manual testing. 138 | 139 | Testing with Vagrant 140 | -------------------- 141 | 142 | Windows/FreeBSD/OpenBSD testing is done with ``kitchen-salt``. 143 | 144 | Requirements 145 | ^^^^^^^^^^^^ 146 | 147 | * Ruby 148 | * Virtualbox 149 | * Vagrant 150 | 151 | Setup 152 | ^^^^^ 153 | 154 | .. code-block:: bash 155 | 156 | $ gem install bundler 157 | $ bundle install --with=vagrant 158 | $ bin/kitchen test [platform] 159 | 160 | Where ``[platform]`` is the platform name defined in ``kitchen.vagrant.yml``, 161 | e.g. ``windows-81-latest-py3``. 162 | 163 | Note 164 | ^^^^ 165 | 166 | When testing using Vagrant you must set the environment variable ``KITCHEN_LOCAL_YAML`` to ``kitchen.vagrant.yml``. For example: 167 | 168 | .. code-block:: bash 169 | 170 | $ KITCHEN_LOCAL_YAML=kitchen.vagrant.yml bin/kitchen test # Alternatively, 171 | $ export KITCHEN_LOCAL_YAML=kitchen.vagrant.yml 172 | $ bin/kitchen test 173 | 174 | Then run the following commands as needed. 175 | 176 | ``bin/kitchen converge`` 177 | ^^^^^^^^^^^^^^^^^^^^^^^^ 178 | 179 | Creates the Vagrant instance and runs the ``openvpn`` main state, ready for testing. 180 | 181 | ``bin/kitchen verify`` 182 | ^^^^^^^^^^^^^^^^^^^^^^ 183 | 184 | Runs the ``inspec`` tests on the actual instance. 185 | 186 | ``bin/kitchen destroy`` 187 | ^^^^^^^^^^^^^^^^^^^^^^^ 188 | 189 | Removes the Vagrant instance. 190 | 191 | ``bin/kitchen test`` 192 | ^^^^^^^^^^^^^^^^^^^^ 193 | 194 | Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``verify`` + ``destroy``. 195 | 196 | ``bin/kitchen login`` 197 | ^^^^^^^^^^^^^^^^^^^^^ 198 | 199 | Gives you RDP/SSH access to the instance for manual testing. 200 | -------------------------------------------------------------------------------- /kitchen.vagrant.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | driver: 5 | name: vagrant 6 | cache_directory: false 7 | customize: 8 | usbxhci: 'off' 9 | gui: false 10 | ssh: 11 | shell: /bin/sh 12 | linked_clone: true 13 | <% unless ENV['CI'] %> 14 | synced_folders: 15 | - - '.kitchen/kitchen-vagrant/%{instance_name}/vagrant' 16 | - '/vagrant' 17 | - 'create: true, disabled: false' 18 | <% end %> 19 | 20 | platforms: 21 | - name: windows-10-latest-py3 22 | driver: 23 | box: techneg/win10x64-pro-salt 24 | cache_directory: "/omnibus/cache" 25 | customize: {} 26 | ssh: {} 27 | provisioner: 28 | # yamllint disable rule:line-length 29 | init_environment: | 30 | # Workaround to allow `kitchen converge` to be used multiple times 31 | # without having to `kitchen destroy` first: remove state files cached by 32 | # Salt during the previous `converge` (if present) 33 | rm -recurse ` 34 | C:\Users\vagrant\AppData\Local\Temp\kitchen\var\cache\salt\minion\files\base ` 35 | -ErrorAction SilentlyContinue 36 | salt-call --local state.single file.managed ` 37 | C:\Users\vagrant\AppData\Local\Temp\kitchen\srv\salt\win\repo-ng\openvpn.sls ` 38 | source=https://github.com/saltstack/salt-winrepo-ng/raw/master/openvpn.sls ` 39 | skip_verify=True makedirs=True 40 | exit 0 41 | # yamllint enable rule:line-length 42 | - name: windows-81-latest-py3 43 | driver: 44 | box: techneg/win81x64-pro-salt 45 | cache_directory: "/omnibus/cache" 46 | customize: {} 47 | ssh: {} 48 | provisioner: 49 | # yamllint disable rule:line-length 50 | init_environment: | 51 | # Workaround to allow `kitchen converge` to be used multiple times 52 | # without having to `kitchen destroy` first: remove state files cached by 53 | # Salt during the previous `converge` (if present) 54 | rm -recurse ` 55 | C:\Users\vagrant\AppData\Local\Temp\kitchen\var\cache\salt\minion\files\base ` 56 | -ErrorAction SilentlyContinue 57 | salt-call --local state.single file.managed ` 58 | C:\Users\vagrant\AppData\Local\Temp\kitchen\srv\salt\win\repo-ng\openvpn.sls ` 59 | source=https://github.com/saltstack/salt-winrepo-ng/raw/master/openvpn.sls ` 60 | skip_verify=True makedirs=True 61 | exit 0 62 | # yamllint enable rule:line-length 63 | -------------------------------------------------------------------------------- /kitchen.windows.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | driver: 5 | name: proxy 6 | host: localhost 7 | reset_command: "exit 0" 8 | port: 5985 9 | username: kitchen 10 | password: Pass@word1 11 | 12 | provisioner: 13 | salt_install: bootstrap 14 | salt_bootstrap_options: -pythonVersion 3 15 | # yamllint disable rule:line-length 16 | init_environment: | 17 | salt-call --local state.single file.managed ` 18 | C:\Users\kitchen\AppData\Local\Temp\kitchen\srv\salt\win\repo-ng\openvpn.sls ` 19 | source=https://github.com/saltstack/salt-winrepo-ng/raw/master/openvpn.sls ` 20 | skip_verify=True makedirs=True 21 | # yamllint enable rule:line-length 22 | 23 | platforms: 24 | - name: windows-2022-latest-py3 25 | - name: windows-2019-latest-py3 26 | -------------------------------------------------------------------------------- /kitchen.yml: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=yaml 3 | --- 4 | # For help on this file's format, see https://kitchen.ci/ 5 | driver: 6 | name: docker 7 | use_sudo: false 8 | privileged: true 9 | run_command: /usr/lib/systemd/systemd 10 | 11 | provisioner: 12 | name: salt_solo 13 | log_level: debug 14 | salt_install: none 15 | require_chef: false 16 | formula: openvpn 17 | salt_copy_filter: 18 | - .kitchen 19 | - .git 20 | 21 | platforms: 22 | ## SALT `tiamat` 23 | - name: debian-11-tiamat-py3 24 | driver: 25 | image: saltimages/salt-tiamat-py3:debian-11 26 | run_command: /lib/systemd/systemd 27 | - name: debian-10-tiamat-py3 28 | driver: 29 | image: saltimages/salt-tiamat-py3:debian-10 30 | run_command: /lib/systemd/systemd 31 | - name: debian-9-tiamat-py3 32 | driver: 33 | image: saltimages/salt-tiamat-py3:debian-9 34 | run_command: /lib/systemd/systemd 35 | - name: ubuntu-2204-tiamat-py3 36 | driver: 37 | image: saltimages/salt-tiamat-py3:ubuntu-22.04 38 | run_command: /lib/systemd/systemd 39 | - name: ubuntu-2004-tiamat-py3 40 | driver: 41 | image: saltimages/salt-tiamat-py3:ubuntu-20.04 42 | run_command: /lib/systemd/systemd 43 | - name: ubuntu-1804-tiamat-py3 44 | driver: 45 | image: saltimages/salt-tiamat-py3:ubuntu-18.04 46 | run_command: /lib/systemd/systemd 47 | - name: centos-stream8-tiamat-py3 48 | driver: 49 | image: saltimages/salt-tiamat-py3:centos-stream8 50 | - name: centos-7-tiamat-py3 51 | driver: 52 | image: saltimages/salt-tiamat-py3:centos-7 53 | - name: amazonlinux-2-tiamat-py3 54 | driver: 55 | image: saltimages/salt-tiamat-py3:amazonlinux-2 56 | - name: oraclelinux-8-tiamat-py3 57 | driver: 58 | image: saltimages/salt-tiamat-py3:oraclelinux-8 59 | - name: oraclelinux-7-tiamat-py3 60 | driver: 61 | image: saltimages/salt-tiamat-py3:oraclelinux-7 62 | - name: almalinux-8-tiamat-py3 63 | driver: 64 | image: saltimages/salt-tiamat-py3:almalinux-8 65 | - name: rockylinux-8-tiamat-py3 66 | driver: 67 | image: saltimages/salt-tiamat-py3:rockylinux-8 68 | 69 | ## SALT `master` 70 | - name: debian-11-master-py3 71 | driver: 72 | image: saltimages/salt-master-py3:debian-11 73 | run_command: /lib/systemd/systemd 74 | - name: debian-10-master-py3 75 | driver: 76 | image: saltimages/salt-master-py3:debian-10 77 | run_command: /lib/systemd/systemd 78 | - name: debian-9-master-py3 79 | driver: 80 | image: saltimages/salt-master-py3:debian-9 81 | run_command: /lib/systemd/systemd 82 | - name: ubuntu-2204-master-py3 83 | driver: 84 | image: saltimages/salt-master-py3:ubuntu-22.04 85 | run_command: /lib/systemd/systemd 86 | - name: ubuntu-2004-master-py3 87 | driver: 88 | image: saltimages/salt-master-py3:ubuntu-20.04 89 | run_command: /lib/systemd/systemd 90 | - name: ubuntu-1804-master-py3 91 | driver: 92 | image: saltimages/salt-master-py3:ubuntu-18.04 93 | run_command: /lib/systemd/systemd 94 | - name: centos-stream8-master-py3 95 | driver: 96 | image: saltimages/salt-master-py3:centos-stream8 97 | - name: centos-7-master-py3 98 | driver: 99 | image: saltimages/salt-master-py3:centos-7 100 | - name: fedora-36-master-py3 101 | driver: 102 | image: saltimages/salt-master-py3:fedora-36 103 | - name: fedora-35-master-py3 104 | driver: 105 | image: saltimages/salt-master-py3:fedora-35 106 | - name: opensuse-leap-153-master-py3 107 | driver: 108 | image: saltimages/salt-master-py3:opensuse-leap-15.3 109 | # Workaround to avoid intermittent failures on `opensuse-leap-15.3`: 110 | # => SCP did not finish successfully (255): (Net::SCP::Error) 111 | transport: 112 | max_ssh_sessions: 1 113 | - name: opensuse-tmbl-latest-master-py3 114 | driver: 115 | image: saltimages/salt-master-py3:opensuse-tumbleweed-latest 116 | # Workaround to avoid intermittent failures on `opensuse-tumbleweed`: 117 | # => SCP did not finish successfully (255): (Net::SCP::Error) 118 | transport: 119 | max_ssh_sessions: 1 120 | - name: amazonlinux-2-master-py3 121 | driver: 122 | image: saltimages/salt-master-py3:amazonlinux-2 123 | - name: oraclelinux-8-master-py3 124 | driver: 125 | image: saltimages/salt-master-py3:oraclelinux-8 126 | - name: oraclelinux-7-master-py3 127 | driver: 128 | image: saltimages/salt-master-py3:oraclelinux-7 129 | - name: arch-base-latest-master-py3 130 | driver: 131 | image: saltimages/salt-master-py3:arch-base-latest 132 | - name: gentoo-stage3-latest-master-py3 133 | driver: 134 | image: saltimages/salt-master-py3:gentoo-stage3-latest 135 | run_command: /sbin/init 136 | - name: gentoo-stage3-systemd-master-py3 137 | driver: 138 | image: saltimages/salt-master-py3:gentoo-stage3-systemd 139 | - name: almalinux-8-master-py3 140 | driver: 141 | image: saltimages/salt-master-py3:almalinux-8 142 | - name: rockylinux-8-master-py3 143 | driver: 144 | image: saltimages/salt-master-py3:rockylinux-8 145 | 146 | ## SALT `3004.1` 147 | - name: debian-11-3004-1-py3 148 | driver: 149 | image: saltimages/salt-3004.1-py3:debian-11 150 | run_command: /lib/systemd/systemd 151 | - name: debian-10-3004-1-py3 152 | driver: 153 | image: saltimages/salt-3004.1-py3:debian-10 154 | run_command: /lib/systemd/systemd 155 | - name: debian-9-3004-1-py3 156 | driver: 157 | image: saltimages/salt-3004.1-py3:debian-9 158 | run_command: /lib/systemd/systemd 159 | - name: ubuntu-2204-3004-1-py3 160 | driver: 161 | image: saltimages/salt-3004.1-py3:ubuntu-22.04 162 | run_command: /lib/systemd/systemd 163 | - name: ubuntu-2004-3004-1-py3 164 | driver: 165 | image: saltimages/salt-3004.1-py3:ubuntu-20.04 166 | run_command: /lib/systemd/systemd 167 | - name: ubuntu-1804-3004-1-py3 168 | driver: 169 | image: saltimages/salt-3004.1-py3:ubuntu-18.04 170 | run_command: /lib/systemd/systemd 171 | - name: centos-stream8-3004-1-py3 172 | driver: 173 | image: saltimages/salt-3004.1-py3:centos-stream8 174 | - name: centos-7-3004-1-py3 175 | driver: 176 | image: saltimages/salt-3004.1-py3:centos-7 177 | - name: fedora-36-3004-1-py3 178 | driver: 179 | image: saltimages/salt-3004.1-py3:fedora-36 180 | - name: fedora-35-3004-1-py3 181 | driver: 182 | image: saltimages/salt-3004.1-py3:fedora-35 183 | - name: amazonlinux-2-3004-1-py3 184 | driver: 185 | image: saltimages/salt-3004.1-py3:amazonlinux-2 186 | - name: oraclelinux-8-3004-1-py3 187 | driver: 188 | image: saltimages/salt-3004.1-py3:oraclelinux-8 189 | - name: oraclelinux-7-3004-1-py3 190 | driver: 191 | image: saltimages/salt-3004.1-py3:oraclelinux-7 192 | - name: arch-base-latest-3004-1-py3 193 | driver: 194 | image: saltimages/salt-3004.1-py3:arch-base-latest 195 | - name: gentoo-stage3-latest-3004-1-py3 196 | driver: 197 | image: saltimages/salt-3004.1-py3:gentoo-stage3-latest 198 | run_command: /sbin/init 199 | - name: gentoo-stage3-systemd-3004-1-py3 200 | driver: 201 | image: saltimages/salt-3004.1-py3:gentoo-stage3-systemd 202 | - name: almalinux-8-3004-1-py3 203 | driver: 204 | image: saltimages/salt-3004.1-py3:almalinux-8 205 | - name: rockylinux-8-3004-1-py3 206 | driver: 207 | image: saltimages/salt-3004.1-py3:rockylinux-8 208 | 209 | ## SALT `3004.0` 210 | - name: opensuse-leap-153-3004-0-py3 211 | driver: 212 | image: saltimages/salt-3004.0-py3:opensuse-leap-15.3 213 | # Workaround to avoid intermittent failures on `opensuse-leap-15.3`: 214 | # => SCP did not finish successfully (255): (Net::SCP::Error) 215 | transport: 216 | max_ssh_sessions: 1 217 | - name: opensuse-tmbl-latest-3004-0-py3 218 | driver: 219 | image: saltimages/salt-3004.0-py3:opensuse-tumbleweed-latest 220 | # Workaround to avoid intermittent failures on `opensuse-tumbleweed`: 221 | # => SCP did not finish successfully (255): (Net::SCP::Error) 222 | transport: 223 | max_ssh_sessions: 1 224 | 225 | ## SALT `3003.4` 226 | - name: debian-10-3003-4-py3 227 | driver: 228 | image: saltimages/salt-3003.4-py3:debian-10 229 | run_command: /lib/systemd/systemd 230 | - name: debian-9-3003-4-py3 231 | driver: 232 | image: saltimages/salt-3003.4-py3:debian-9 233 | run_command: /lib/systemd/systemd 234 | - name: ubuntu-2004-3003-4-py3 235 | driver: 236 | image: saltimages/salt-3003.4-py3:ubuntu-20.04 237 | run_command: /lib/systemd/systemd 238 | - name: ubuntu-1804-3003-4-py3 239 | driver: 240 | image: saltimages/salt-3003.4-py3:ubuntu-18.04 241 | run_command: /lib/systemd/systemd 242 | - name: centos-stream8-3003-4-py3 243 | driver: 244 | image: saltimages/salt-3003.4-py3:centos-stream8 245 | - name: centos-7-3003-4-py3 246 | driver: 247 | image: saltimages/salt-3003.4-py3:centos-7 248 | - name: amazonlinux-2-3003-4-py3 249 | driver: 250 | image: saltimages/salt-3003.4-py3:amazonlinux-2 251 | - name: oraclelinux-8-3003-4-py3 252 | driver: 253 | image: saltimages/salt-3003.4-py3:oraclelinux-8 254 | - name: oraclelinux-7-3003-4-py3 255 | driver: 256 | image: saltimages/salt-3003.4-py3:oraclelinux-7 257 | - name: almalinux-8-3003-4-py3 258 | driver: 259 | image: saltimages/salt-3003.4-py3:almalinux-8 260 | 261 | verifier: 262 | # https://www.inspec.io/ 263 | name: inspec 264 | sudo: true 265 | reporter: 266 | # cli, documentation, html, progress, json, json-min, json-rspec, junit 267 | - cli 268 | # This formula has InSpec controls which involve retrying tests, to allow time, 269 | # for example, for services to start up fully. These retries will not pick 270 | # up these changes if the backend cache is in use, so it's set to `false` here. 271 | backend_cache: false 272 | 273 | suites: 274 | - name: default 275 | provisioner: 276 | state_top: 277 | base: 278 | '*': 279 | - openvpn._mapdata 280 | - openvpn.config 281 | pillars: 282 | top.sls: 283 | base: 284 | '*': 285 | - openvpn 286 | pillars_from_files: 287 | openvpn.sls: test/salt/pillar/default.sls 288 | verifier: 289 | inspec_tests: 290 | - path: test/integration/default 291 | -------------------------------------------------------------------------------- /openvpn/_mapdata/_mapdata.jinja: -------------------------------------------------------------------------------- 1 | # yamllint disable rule:indentation rule:line-length 2 | # {{ grains.get("osfinger", grains.os) }} 3 | --- 4 | {#- use salt.slsutil.serialize to avoid encoding errors on some platforms #} 5 | {{ salt["slsutil.serialize"]( 6 | "yaml", 7 | map, 8 | default_flow_style=False, 9 | allow_unicode=True, 10 | ) 11 | | regex_replace("^\s+'$", "'", multiline=True) 12 | | trim 13 | }} 14 | -------------------------------------------------------------------------------- /openvpn/_mapdata/init.sls: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # vim: ft=sls 3 | --- 4 | {#- Get the `tplroot` from `tpldir` #} 5 | {%- set tplroot = tpldir.split("/")[0] %} 6 | {%- from tplroot ~ "/map.jinja" import mapdata with context %} 7 | 8 | {%- set _mapdata = { 9 | "values": mapdata, 10 | } %} 11 | {%- do salt["log.debug"]("### MAP.JINJA DUMP ###\n" ~ _mapdata | yaml(False)) %} 12 | 13 | {%- set output_dir = "/temp" if grains.os_family == "Windows" else "/tmp" %} 14 | {%- set output_file = output_dir ~ "/salt_mapdata_dump.yaml" %} 15 | 16 | {{ tplroot }}-mapdata-dump: 17 | file.managed: 18 | - name: {{ output_file }} 19 | - source: salt://{{ tplroot }}/_mapdata/_mapdata.jinja 20 | - template: jinja 21 | - context: 22 | map: {{ _mapdata | yaml }} 23 | -------------------------------------------------------------------------------- /openvpn/adapters.sls: -------------------------------------------------------------------------------- 1 | {% if salt['grains.get']('os_family') == 'Windows' %} 2 | include: 3 | - openvpn 4 | 5 | {% for type, names in salt['pillar.get']('openvpn', {}).items() %} 6 | {% if type in ['client', 'server', 'peer'] %} 7 | {% for name, config in names.items() %} 8 | {% if config.dev_node is defined %} 9 | openvpn_tap_adapter_{{ config.dev_node }}: 10 | cmd.script: 11 | - source: salt://openvpn/files/tap-adapter.ps1 12 | - args: -New {{ config.dev_node }} 13 | - shell: powershell 14 | - stateful: True 15 | - require: 16 | - pkg: openvpn_pkgs 17 | {% endif %} 18 | {% endfor %} 19 | {% endif %} 20 | {% endfor %} 21 | 22 | {% endif %} 23 | -------------------------------------------------------------------------------- /openvpn/config.sls: -------------------------------------------------------------------------------- 1 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 2 | {% from "openvpn/macros.jinja" import multipart_param with context %} 3 | 4 | include: 5 | - openvpn 6 | - openvpn.general_config 7 | 8 | {% for type, names in salt['pillar.get']('openvpn', {}).items() %} 9 | {% if type in ['client', 'server', 'peer'] %} 10 | {% for name, config in names.items() %} 11 | 12 | {% macro _permissions(mode=644, user=None, group=None) %} 13 | {%- if not grains['os_family'] == 'Windows' -%} 14 | - mode: {{ mode }} 15 | - user: {% if not user is none %}{{ user }}{% elif config.user is defined %}{{ config.user }}{% else %}{{ map.user }}{% endif %} 16 | - group: {% if not group is none %}{{ group }}{% elif config.group is defined %}{{ config.group }}{% else %}{{ map.group }}{% endif %} 17 | {%- endif -%} 18 | {% endmacro %} 19 | 20 | {% set service_id = "openvpn_{0}_service".format(name) if map.multi_services else "openvpn_service" %} 21 | 22 | {%- if config.conf_dir is defined %} 23 | {#- Use the explicit config from Pillar, if it is present. #} 24 | {%- set config_dir = config.conf_dir %} 25 | {%- else %} 26 | {#- Some distributions use /etc/openvpn/{client,server} as their working directory #} 27 | {%- set config_dir = map.get(type, {}).get("conf_dir", map.conf_dir) %} 28 | {%- endif %} 29 | 30 | {%- set config_file = "{0}/openvpn_{1}.conf".format( 31 | config_dir, 32 | name, 33 | ) if map.multi_services and grains['os_family'] == 'FreeBSD' else "{0}/{1}.{2}".format( 34 | config_dir, 35 | name, 36 | map.conf_ext, 37 | ) %} 38 | 39 | # Deploy {{ type }} {{ name }} config files 40 | openvpn_config_{{ type }}_{{ name }}: 41 | file.managed: 42 | - name: {{ config_file }} 43 | {{ _permissions(640, 'root') }} 44 | - source: 45 | - salt://openvpn/files/{{ type }}.jinja 46 | - salt://openvpn/files/common_opts.jinja # make available to salt-ssh 47 | # see https://github.com/saltstack/salt/issues/21370#issuecomment-226868952 48 | - template: jinja 49 | - context: 50 | name: {{ name }} 51 | type: {{ type }} 52 | user: {{ map.user }} 53 | group: {{ map.group }} 54 | config: {{ config | json }} 55 | - watch_in: 56 | - service: {{ service_id }} 57 | 58 | {% if config.ca is defined and config.ca_content is defined %} 59 | # Deploy {{ type }} {{ name }} CA file 60 | openvpn_config_{{ type }}_{{ name }}_ca_file: 61 | file.managed: 62 | - name: {{ config.ca }} 63 | {{ _permissions(640, 'root') }} 64 | - contents_pillar: openvpn:{{ type }}:{{ name }}:ca_content 65 | - makedirs: True 66 | - watch_in: 67 | - service: {{ service_id }} 68 | {% endif %} 69 | 70 | {% if config.cert is defined and config.cert_content is defined %} 71 | # Deploy {{ type }} {{ name }} certificate file 72 | openvpn_config_{{ type }}_{{ name }}_cert_file: 73 | file.managed: 74 | - name: {{ config.cert }} 75 | {{ _permissions(640, 'root') }} 76 | - contents_pillar: openvpn:{{ type }}:{{ name }}:cert_content 77 | - makedirs: True 78 | - watch_in: 79 | - service: {{ service_id }} 80 | {% endif %} 81 | 82 | {% if config.key is defined and config.key_content is defined %} 83 | # Deploy {{ type }} {{ name }} private key file 84 | openvpn_config_{{ type }}_{{ name }}_key_file: 85 | file.managed: 86 | - name: {{ config.key }} 87 | {{ _permissions(600, 'root') }} 88 | - contents_pillar: openvpn:{{ type }}:{{ name }}:key_content 89 | - makedirs: True 90 | - watch_in: 91 | - service: {{ service_id }} 92 | {% endif %} 93 | 94 | {% if config.crl_verify is defined and config.crl_verify_content is defined %} 95 | # Deploy {{ type }} {{ name }} crl file 96 | openvpn_config_{{ type }}_{{ name }}_crl_verify_file: 97 | file.managed: 98 | - name: {{ config.crl_verify }} 99 | {{ _permissions(640, 'root') }} 100 | - contents_pillar: openvpn:{{ type }}:{{ name }}:crl_verify_content 101 | - makedirs: True 102 | - watch_in: 103 | - service: {{ service_id }} 104 | {% endif %} 105 | 106 | {% if config.askpass is defined and config.askpass_content is defined %} 107 | # Deploy {{ type }} {{ name }} private key password file 108 | openvpn_config_{{ type }}_{{ name }}_passwd_file: 109 | file.managed: 110 | - name: {{ config.askpass }} 111 | {{ _permissions(600, 'root') }} 112 | - contents_pillar: openvpn:{{ type }}:{{ name }}:askpass_content 113 | - makedirs: True 114 | - watch_in: 115 | - service: {{ service_id }} 116 | {% endif %} 117 | 118 | {% if config.ta_content is defined and config.tls_crypt is defined %} 119 | # Deploy {{ type }} {{ name }} TLS key file 120 | openvpn_config_{{ type }}_{{ name }}_tls_crypt_file: 121 | file.managed: 122 | - name: {{ config.tls_crypt }} 123 | {{ _permissions(600, 'root') }} 124 | - contents_pillar: openvpn:{{ type }}:{{ name }}:ta_content 125 | - makedirs: True 126 | - watch_in: 127 | - service: {{ service_id }} 128 | {% elif config.ta_content is defined and config.tls_auth is defined %} 129 | # Deploy {{ type }} {{ name }} TLS key file 130 | openvpn_config_{{ type }}_{{ name }}_tls_auth_file: 131 | file.managed: 132 | - name: {{ multipart_param(config.tls_auth, 0) }} 133 | {{ _permissions(600, 'root') }} 134 | - contents_pillar: openvpn:{{ type }}:{{ name }}:ta_content 135 | - makedirs: True 136 | - watch_in: 137 | - service: {{ service_id }} 138 | {% endif %} 139 | 140 | {% if config.secret is defined and config.secret_content is defined %} 141 | # Deploy {{ type }} {{ name }} shared secret key file 142 | openvpn_config_{{ type }}_{{ name }}_secret_file: 143 | file.managed: 144 | - name: {{ multipart_param(config.secret, 0) }} 145 | {{ _permissions(600, 'root') }} 146 | - contents_pillar: openvpn:{{ type }}:{{ name }}:secret_content 147 | - makedirs: True 148 | - watch_in: 149 | - service: {{ service_id }} 150 | {% endif %} 151 | 152 | {% if config.auth_user_pass is defined and config.auth_user_pass_content is defined %} 153 | # Deploy {{ type }} {{ name }} auth_user_pass file 154 | openvpn_config_{{ type }}_{{ name }}_auth_user_pass_file: 155 | file.managed: 156 | - name: {{ config.auth_user_pass }} 157 | {{ _permissions(600, 'root') }} 158 | - contents_pillar: openvpn:{{ type }}:{{ name }}:auth_user_pass_content 159 | - makedirs: True 160 | - watch_in: 161 | - service: {{ service_id }} 162 | {% endif %} 163 | 164 | {% if config.status is defined %} 165 | # Ensure status file exists and is writeable 166 | openvpn_{{ type }}_{{ name }}_status_file: 167 | file.managed: 168 | - name: {{ config.status }} 169 | - makedirs: True 170 | {{ _permissions(600, 'root', 0) }} # different group names on FreeBSD and Debian/Ubuntu 171 | - watch_in: 172 | {%- if map.multi_services %} 173 | - service: openvpn_{{ name }}_service 174 | {%- else %} 175 | - service: openvpn_service 176 | {%- endif %} 177 | {% endif %} 178 | 179 | {% if config.log is defined %} 180 | # Ensure log file exists and is writeable 181 | openvpn_{{ type }}_{{ name }}_log_file: 182 | file.managed: 183 | - name: {{ config.log }} 184 | - makedirs: True 185 | - replace: False 186 | {{ _permissions(640, map.log_user) }} 187 | - require_in: 188 | {%- if map.multi_services %} 189 | - service: openvpn_{{ name }}_service 190 | {%- else %} 191 | - service: openvpn_service 192 | {%- endif %} 193 | {% endif %} 194 | 195 | {% if config.log_append is defined %} 196 | # Ensure log file exists and is writeable 197 | openvpn_{{ type }}_{{ name }}_log_file_append: 198 | file.managed: 199 | - name: {{ config.log_append }} 200 | - makedirs: True 201 | - replace: False 202 | {{ _permissions(640, map.log_user) }} 203 | - require_in: 204 | {%- if map.multi_services %} 205 | - service: openvpn_{{ name }}_service 206 | {%- else %} 207 | - service: openvpn_service 208 | {%- endif %} 209 | {% endif %} 210 | 211 | {% if config.client_config_dir is defined %} 212 | # Ensure client config dir exists 213 | openvpn_config_{{ type }}_{{ name }}_client_config_dir: 214 | file.directory: 215 | - name: {{ config_dir }}/{{ config.client_config_dir }} 216 | {{ _permissions(750, 'root') }} 217 | - makedirs: True 218 | - watch_in: 219 | {%- if map.multi_services %} 220 | - service: openvpn_{{ name }}_service 221 | {%- else %} 222 | - service: openvpn_service 223 | {%- endif %} 224 | 225 | {% for client, client_config in salt['pillar.get']('openvpn:'+type+':'+name+':client_config', {}).items() %} 226 | # Client config for {{ client }} 227 | openvpn_config_{{ type }}_{{ name }}_{{ client }}_client_config: 228 | file.managed: 229 | - name: {{ config_dir }}/{{ config.client_config_dir }}/{{ client }} 230 | {{ _permissions(640, 'root') }} 231 | - contents_pillar: openvpn:{{ type }}:{{ name }}:client_config:{{ client }} 232 | - makedirs: True 233 | - watch_in: 234 | - service: {{ service_id }} 235 | {% endfor %} 236 | {% endif %} 237 | 238 | {% endfor %} 239 | {% endif %} 240 | {% endfor %} 241 | -------------------------------------------------------------------------------- /openvpn/dhparams.sls: -------------------------------------------------------------------------------- 1 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 2 | 3 | # Generate diffie hellman files 4 | {% if salt['pillar.get']('openvpn:server', False) %} 5 | {#- Some distributions use /etc/openvpn/{client,server} as their working directory #} 6 | {%- set config_dir = map.get("server", {}).get("conf_dir", map.conf_dir) %} 7 | {%- for dh in map.dh_files %} 8 | {%- set dh_file = config_dir ~ "/dh" ~ dh ~ ".pem" %} 9 | openvpn_create_dh_{{ dh }}: 10 | cmd.run: 11 | - name: '"{{ map.bin_dir | default('', true) }}openssl" dhparam {% if map.dsaparam %}-dsaparam {% endif %}-out "{{ dh_file }}" {{ dh }}' 12 | - creates: {{ dh_file }} 13 | - require: 14 | - pkg: openvpn_pkgs 15 | {%- endfor %} 16 | {% endif %} 17 | -------------------------------------------------------------------------------- /openvpn/files/client.jinja: -------------------------------------------------------------------------------- 1 | # OpenVPN client configuration '{{ name }}' 2 | # Managed by Salt 3 | # Template: {{ source }} 4 | 5 | {% include 'openvpn/files/common_opts.jinja' %} 6 | 7 | {%- if not (config.pull is defined and config.pull == False) %} 8 | pull 9 | {% endif %} 10 | 11 | {%- if not (config.tls_client is defined and config.tls_client == False) %} 12 | tls-client 13 | {%- endif %} 14 | 15 | {%- if config.resolv_retry is defined %} 16 | resolv-retry {{ config.resolv_retry }} 17 | {%- else %} 18 | resolv-retry infinite 19 | {%- endif %} 20 | 21 | {%- if not (config.nobind is defined and config.nobind == False) %} 22 | nobind 23 | {%- endif %} 24 | 25 | {%- if config.http_proxy_retry is defined %} 26 | http-proxy-retry 27 | {%- endif %} 28 | 29 | {%- if config.http_proxy is defined %} 30 | http-proxy {{ config.http_proxy }} 31 | {%- endif %} 32 | 33 | {%- if config.auth_user_pass is defined %} 34 | auth-user-pass {{ config.auth_user_pass }} 35 | {%- endif %} 36 | 37 | {%- if config.auth_nocache is defined %} 38 | auth-nocache 39 | {%- endif %} 40 | -------------------------------------------------------------------------------- /openvpn/files/common_opts.jinja: -------------------------------------------------------------------------------- 1 | {% from "openvpn/macros.jinja" import multipart_param with context %} 2 | 3 | {%- if config.daemon is defined and config.daemon == True %} 4 | daemon 5 | {%- endif -%} 6 | 7 | ; Networking 8 | {%- if config.dev_node is defined %} 9 | dev-node {{ config.dev_node }} 10 | {%- endif %} 11 | 12 | {%- if config.dev_type is defined %} 13 | dev-type {{ config.dev_type }} 14 | {%- endif %} 15 | 16 | {%- if config.tun_ipv6 is defined and config.tun_ipv6 == True %} 17 | tun-ipv6 18 | {%- endif %} 19 | 20 | {%- if config.proto is defined %} 21 | proto {{ config.proto }} 22 | {%- else %} 23 | proto udp 24 | {%- endif %} 25 | 26 | {%- if config.port is defined %} 27 | port {{ config.port }} 28 | {%- else %} 29 | port 1194 30 | {%- endif %} 31 | 32 | {%- if config.ping is defined %} 33 | ping {{ config.ping }} 34 | {%- endif %} 35 | 36 | {%- if config.ping_restart is defined %} 37 | ping-restart {{ config.ping_restart }} 38 | {%- endif %} 39 | 40 | {%- if config.ping_exit is defined %} 41 | ping-exit {{ config.ping_exit }} 42 | {%- endif %} 43 | 44 | {%- if config.ping_timer_rem is defined %} 45 | ping-timer-rem 46 | {%- endif %} 47 | 48 | {%- if config.keepalive is defined %} 49 | keepalive {{ config.keepalive }} 50 | {%- endif %} 51 | 52 | {%- if config.persist_remote_ip is defined and config.persist_remote_ip == True %} 53 | persist-remote-ip 54 | {%- endif %} 55 | 56 | {%- if config.tun_mtu is defined %} 57 | tun-mtu {{ config.tun_mtu }} 58 | {%- endif %} 59 | 60 | {%- if config.ifconfig_ipv6 is defined %} 61 | ifconfig-ipv6 {{ config.ifconfig_ipv6 }} 62 | {%- endif %} 63 | 64 | {%- if config.ifconfig is defined %} 65 | ifconfig {{ config.ifconfig }} 66 | {%- endif %} 67 | 68 | {%- if config.secret is defined %}{# Using simple site-to-site shared secret #} 69 | ; Site-to-Site 70 | secret {{ multipart_param(config.secret) }} 71 | {%- endif %} 72 | 73 | {%- if config.remote is defined %} 74 | {%- for remote in config.remote %} 75 | remote {{ remote }} 76 | {%- endfor %} 77 | {%- endif %} 78 | 79 | {%- if config.remote_random is defined %} 80 | remote-random 81 | {%- endif %} 82 | 83 | 84 | ; Operating system 85 | {%- if config.dev is defined %} 86 | dev {{ config.dev }} 87 | {%- else %} 88 | dev tun 89 | {%- endif %} 90 | 91 | {%- if config.user is defined %} 92 | user {{ config.user }} 93 | {%- else %} 94 | user {{ user }} 95 | {%- endif %} 96 | 97 | {%- if config.group is defined %} 98 | group {{ config.group }} 99 | {%- else %} 100 | group {{ group }} 101 | {%- endif %} 102 | 103 | {%- if not (config.persist_key is defined and config.persist_key == False) %} 104 | persist-key 105 | {%- endif %} 106 | 107 | {%- if not (config.persist_tun is defined and config.persist_tun == False) %} 108 | persist-tun 109 | {%- endif %} 110 | 111 | 112 | ; Data transfer 113 | {%- if config.comp_lzo is defined and config.comp_lzo == False %} 114 | comp-lzo no 115 | {%- elif config.comp_lzo is defined %} 116 | comp-lzo {{ config.comp_lzo }} 117 | {%- endif %} 118 | 119 | 120 | ; Logging / Debugging 121 | {%- if config.verb is defined %} 122 | verb {{ config.verb }} 123 | {%- else %} 124 | verb 3 125 | {%- endif %} 126 | 127 | {%- if config.status is defined %} 128 | status {{ config.status }} 129 | {%- endif %} 130 | 131 | {%- if config.log is defined %} 132 | log {{ config.log }} 133 | {%- endif %} 134 | 135 | {%- if config.log_append is defined %} 136 | log-append {{ config.log_append }} 137 | {%- endif %} 138 | 139 | {%- if config.syslog is defined and config.syslog %} 140 | syslog {%- if config.syslog is string %} {{ config.syslog }}{% endif %} 141 | {%- endif %} 142 | 143 | {%- if config.mute_replay_warnings is defined %} 144 | mute-replay-warnings 145 | {%- endif %} 146 | 147 | {%- if config.mute is defined %} 148 | mute {{ config.mute }} 149 | {%- endif %} 150 | 151 | 152 | ; Cryptographic parameters 153 | {%- if config.ca is defined %} 154 | ca {{ config.ca }} 155 | {%- else %} 156 | # ca is not set ! 157 | {%- endif %} 158 | 159 | {%- if config.crl_verify is defined %} 160 | crl-verify {{ config.crl_verify }} 161 | {%- endif %} 162 | 163 | {%- if config.cert is defined %} 164 | cert {{ config.cert }} 165 | {%- else %} 166 | # cert is not set ! 167 | {%- endif %} 168 | 169 | {%- if config.key is defined %} 170 | key {{ config.key }} 171 | {%- else %} 172 | # key is not set ! 173 | {%- endif %} 174 | 175 | {%- if config.pkcs12 is defined %} 176 | pkcs12 {{ config.pkcs12 }} 177 | {%- endif %} 178 | 179 | {%- if config.dh is defined %} 180 | dh {{ config.dh }} 181 | {%- elif config.server is defined %} 182 | dh dh1024.pem 183 | {%- endif %} 184 | 185 | {%- if config.tls_crypt is defined %} 186 | tls-crypt {{ config.tls_crypt }} 187 | {%- elif config.tls_auth is defined %} 188 | tls-auth {{ multipart_param(config.tls_auth) }} 189 | {%- endif %} 190 | 191 | {%- if config.reneg_sec is defined %} 192 | reneg-sec {{ config.reneg_sec }} 193 | {%- endif %} 194 | 195 | ; check with https://bettercrypto.org/static/applied-crypto-hardening.pdf 196 | {%- if config.auths is defined %} 197 | {%- for auth in config.auths %} 198 | auth "{{ auth }}" 199 | {%- endfor %} 200 | {%- endif %} 201 | 202 | {%- if config.ciphers is defined %} 203 | {%- for cipher in config.ciphers %} 204 | cipher "{{ cipher }}" 205 | {%- endfor %} 206 | {%- endif %} 207 | 208 | {%- if config.tls_cipher is defined %} 209 | tls-cipher {{ config.tls_cipher }} 210 | {%- endif %} 211 | 212 | {%- if config.tls_version_min is defined %} 213 | tls-version-min {{ config.tls_version_min }} 214 | {%- endif %} 215 | 216 | {%- if config.tls_version_max is defined %} 217 | tls-version-max {{ config.tls_version_max }} 218 | {%- endif %} 219 | 220 | ; Certificate verification 221 | ; (Anti MITM) 222 | {%- if config.verify_x509_name is defined %} 223 | verify-x509-name {{ config.verify_x509_name }} 224 | {%- endif %} 225 | 226 | {%- if config.ns_cert_type is defined %} 227 | ns-cert-type {{ config.ns_cert_type }} 228 | {%- endif %} 229 | 230 | {%- if config.remote_cert_tls is defined %} 231 | remote-cert-tls {{ config.remote_cert_tls }} 232 | {%- endif %} 233 | 234 | {%- if config.askpass is defined %} 235 | askpass {{ config.askpass }} 236 | {%- endif %} 237 | 238 | 239 | ; Up/Down Scripts 240 | {%- if config.up is defined %} 241 | up {{ config.up }} 242 | {%- endif %} 243 | 244 | {%- if config.up_delay is defined %} 245 | up-delay 246 | {%- endif %} 247 | 248 | {%- if config.down is defined %} 249 | down {{ config.down }} 250 | {%- endif %} 251 | 252 | {%- if config.down_pre is defined %} 253 | down-pre 254 | {%- endif %} 255 | 256 | {%- if config.up_restart is defined %} 257 | up-restart 258 | {%- endif %} 259 | 260 | {%- if config._append is defined %} 261 | ; Append arbitrary parameters 262 | {%- for data in config._append %} 263 | {{ data }} 264 | {%- endfor %} 265 | {%- endif %} 266 | 267 | {# backwards compatibility #} 268 | {%- if config.auth is defined %} 269 | auth {{ config.auth }} 270 | {%- endif %} 271 | 272 | {%- if config.fast_io is defined %} 273 | fast-io 274 | {%- endif %} 275 | 276 | {%- if config.key_direction is defined %} 277 | key-direction {{ config.key_direction }} 278 | {% endif %} 279 | 280 | {%- if config.route_method is defined %} 281 | route-method {{ config.route_method }} 282 | {% endif %} 283 | 284 | {%- if config.route_delay is defined %} 285 | route-delay {{ config.route_delay }} 286 | {% endif %} 287 | 288 | {%- if config.route_nopull is defined %} 289 | route-nopull 290 | {% endif %} 291 | 292 | {%- if config.route_ipv6 is defined %} 293 | {%- for route in config.route_ipv6 %} 294 | route-ipv6 {{ route }} 295 | {%- endfor %} 296 | {%- endif %} 297 | 298 | {%- if config.route is defined %} 299 | {%- for route in config.route %} 300 | route {{ route }} 301 | {%- endfor %} 302 | {%- endif %} 303 | 304 | {%- if config.fragment is defined %} 305 | fragment {{ config.fragment }} 306 | {% endif %} 307 | 308 | {%- if config.mssfix is defined %} 309 | mssfix {{ config.mssfix }} 310 | {% endif %} 311 | 312 | {%- if config.keysize is defined %} 313 | keysize {{ config.keysize }} 314 | {% endif %} 315 | 316 | {%- if config.sndbuf is defined %} 317 | sndbuf {{ config.sndbuf }} 318 | {% endif %} 319 | 320 | {%- if config.rcvbuf is defined %} 321 | rcvbuf {{ config.rcvbuf }} 322 | {% endif %} 323 | 324 | {% if config.get('float', False) -%} 325 | float 326 | {%- endif %} 327 | 328 | {%- if config.script_security is defined %} 329 | script-security {{ config.script_security }} 330 | {%- endif %} 331 | -------------------------------------------------------------------------------- /openvpn/files/ifconfig_pool_persist.jinja: -------------------------------------------------------------------------------- 1 | {%- for host, ip in config.items() %} 2 | {{ host }},{{ ip }} 3 | {%- endfor %} 4 | -------------------------------------------------------------------------------- /openvpn/files/openvpn-1.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saltstack-formulas/openvpn-formula/1859248c332dd28f88e3e4e2e3ec1df875a5f59c/openvpn/files/openvpn-1.cer -------------------------------------------------------------------------------- /openvpn/files/openvpn-2.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFsDCCBJigAwIBAgIQCy3tkBteg/fWDOrC2nic7DANBgkqhkiG9w0BAQsFADBs 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBFViBDb2RlIFNpZ25p 5 | bmcgQ0EgKFNIQTIpMB4XDTE5MDIxMzAwMDAwMFoXDTIyMDIyMzEyMDAwMFowgcYx 6 | EzARBgsrBgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUx 7 | HTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRAwDgYDVQQFEwczNzYxMjU2 8 | MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTETMBEGA1UEBxMKUGxl 9 | YXNhbnRvbjEVMBMGA1UEChMMT3BlblZQTiBJbmMuMRUwEwYDVQQDEwxPcGVuVlBO 10 | IEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBkcQPXtX3Pvdz 11 | Lk1FN0K9CdtMdfVtXFUSU8IR2ksKqSBn3AKfQbdHFAHVVb46TjXzIdstAdUoBLxZ 12 | 3JBJ63IR74taRZdtuXFJTd2y3pBlUEjbXhZjsMpmcTIvMM9NAbWZKndrBwyMzqln 13 | wdURgLlP29KivTNcctSCWmD95yhQ6SW6U8zAmk6ttSJJIPPCdDmY8m6qzgByOQ7K 14 | FxH+y1IupAqimtIed+vZxjPZYHEDEzE20n1hoIS2avVL96zN9zlLRQTwO5uRABgm 15 | NtI0s3Ln4nM9M/am0cTYMribKKjXkPvXlhHnbyqCTaD2mgZo4DzjvBK8g/GciEwY 16 | rnJ7hEW5AgMBAAGjggHxMIIB7TAfBgNVHSMEGDAWgBSP6H7wbTJqAAUjx3CXajqQ 17 | /2vq1DAdBgNVHQ4EFgQU/mOc7P1ax1MKxuNY4QrWDGR85cAwLgYDVR0RBCcwJaAj 18 | BggrBgEFBQcIA6AXMBUME1VTLURFTEFXQVJFLTM3NjEyNTYwDgYDVR0PAQH/BAQD 19 | AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6 20 | Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9FVkNvZGVTaWduaW5nU0hBMi1nMS5jcmwwN6A1 21 | oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9FVkNvZGVTaWduaW5nU0hBMi1n 22 | MS5jcmwwSwYDVR0gBEQwQjA3BglghkgBhv1sAwIwKjAoBggrBgEFBQcCARYcaHR0 23 | cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAHBgVngQwBAzB+BggrBgEFBQcBAQRy 24 | MHAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBIBggrBgEF 25 | BQcwAoY8aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0RVZDb2Rl 26 | U2lnbmluZ0NBLVNIQTIuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD 27 | ggEBABnMHBLp/++Urgq2bogoGr85oks8Rtqq6Ok2z5R83eVfULu82kUSYZruD6yT 28 | Y5QnwRRLrHEopGLmmVKeW0Sx268pHmA0oIj4BWpP26MvGV9tu94iOKeE0q6gGF3B 29 | 24Y+Q6OLme5vt4HbhEgO/VYR3/1y8gJC36Up08jovxYA3Tgp4TfDbheF4di9SwFK 30 | UeIsOG/TTQZc83e7oaBjfNmCx6apNR3C6AgcB7dDpx4GaD45Sw47ugXCrUA08Whc 31 | 4rmPa9tcClJFzXec1NQQHlCVCKE6l4fahsWiZ0jCLi6tBvwvnyfLQr1nmDnMBizf 32 | rJOVTw+ay+C0xRbp9MNfnprsrEY= 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /openvpn/files/peer.jinja: -------------------------------------------------------------------------------- 1 | # OpenVPN peer configuration '{{ name }}' 2 | # Managed by Salt 3 | # Template: {{ source }} 4 | 5 | {% include 'openvpn/files/common_opts.jinja' %} 6 | {% include 'openvpn/files/server.jinja' %} 7 | -------------------------------------------------------------------------------- /openvpn/files/server.jinja: -------------------------------------------------------------------------------- 1 | # OpenVPN server configuration '{{ name }}' 2 | # Managed by Salt 3 | # Template: {{ source }} 4 | 5 | {% include 'openvpn/files/common_opts.jinja' %} 6 | {%- set config = salt['pillar.get']("openvpn:{}:{}".format(type, name), {}) %} 7 | 8 | 9 | {%- if not (config.tls_server is defined and config.tls_server == False) %} 10 | {%- if not (config.secret is defined) %} 11 | tls-server 12 | {%- endif %} 13 | {%- endif %} 14 | 15 | {%- if config.local is defined %} 16 | local {{ config.local }} 17 | {%- endif %} 18 | 19 | {%- if config.port_share is defined %} 20 | port-share {{ config.port_share }} 21 | {%- endif %} 22 | 23 | {%- if config.topology is defined %} 24 | topology {{ config.topology }} 25 | {%- endif %} 26 | 27 | {%- if config.server is defined %} 28 | server {{ config.server }} 29 | {%- elif config.server_bridge is defined %} 30 | server-bridge {{ config.server_bridge }} 31 | {%- elif config.mode is defined %} 32 | mode {{ config.mode }} 33 | {%- endif %} 34 | 35 | {%- if config.ifconfig_pool is defined %} 36 | ifconfig-pool {{ config.ifconfig_pool }} 37 | {%- endif %} 38 | 39 | {%- if config.server_ipv6 is defined %} 40 | server-ipv6 {{ config.server_ipv6 }} 41 | {%- endif %} 42 | 43 | {%- if config.ifconfig_ipv6 is defined %} 44 | ifconfig-ipv6 {{ config.ifconfig_ipv6 }} 45 | {%- endif %} 46 | 47 | {%- if config.ifconfig_ipv6_pool is defined %} 48 | ifconfig-ipv6-pool {{ config.ifconfig_ipv6_pool }} 49 | {%- endif %} 50 | 51 | {%- if config.ifconfig_pool_persist is defined %} 52 | ifconfig-pool-persist {{ config.ifconfig_pool_persist }} 53 | {%- endif %} 54 | 55 | {%- if config.server_bridge is defined %} 56 | server-bridge {{ config.server_bridge }} 57 | {%- endif %} 58 | 59 | {%- if config.push is defined %} 60 | {%- for push in config.push %} 61 | push "{{ push }}" 62 | {%- endfor %} 63 | {%- endif %} 64 | 65 | {%- if config.client_config_dir is defined %} 66 | client-config-dir {{ config.client_config_dir }} 67 | {%- endif %} 68 | 69 | {%- if config.learn_address is defined %} 70 | learn-address {{ config.learn_address }} 71 | {%- endif %} 72 | 73 | {%- if config.client_to_client is defined and config.client_to_client == True %} 74 | client-to-client 75 | {%- endif %} 76 | 77 | {%- if config.duplicate_cn is defined and config.duplicate_cn == True %} 78 | duplicate-cn 79 | {%- endif %} 80 | 81 | {%- if config.max_clients is defined %} 82 | max-clients {{ config.max_clients }} 83 | {%- endif %} 84 | 85 | {%- if config.ccd_exclusive is defined and config.ccd_exclusive == True %} 86 | ccd-exclusive 87 | {%- endif %} 88 | 89 | {%- if config.username_as_common_name is defined and config.username_as_common_name == True %} 90 | username-as-common-name 91 | {%- endif %} 92 | 93 | {%- if config.plugins is defined %} 94 | {%- for plugin in config.plugins %} 95 | plugin {{ plugin }} 96 | {%- endfor %} 97 | {%- endif %} 98 | 99 | {%- if config.client_cert_not_required is defined %} 100 | client-cert-not-required 101 | {%- endif %} 102 | 103 | {%- if config.verify_client_cert is defined %} 104 | verify-client-cert {{ config.verify_client_cert }} 105 | {%- endif %} 106 | 107 | {%- if config.management is defined %} 108 | management {{ config.management }} 109 | {%- endif %} 110 | 111 | {%- if config.auth_user_pass_verify is defined %} 112 | auth-user-pass-verify {{ config.auth_user_pass_verify }} 113 | {%- endif %} 114 | 115 | {#- `false is number` and `true is number` both also return true... #} 116 | {%- if config.auth_gen_token is defined 117 | and (config.auth_gen_token|int is sameas (config.auth_gen_token) 118 | or config.auth_gen_token is sameas true) %} 119 | auth-gen-token{% if config.auth_gen_token is not sameas true %} {{ config.auth_gen_token|int }}{% endif %} 120 | {%- endif %} 121 | 122 | {%- if config.setenv is defined %} 123 | {%- for setenv in config.setenv %} 124 | setenv {{ setenv }} 125 | {% endfor %} 126 | {% endif %} 127 | -------------------------------------------------------------------------------- /openvpn/files/tap-adapter.ps1: -------------------------------------------------------------------------------- 1 | param([Parameter(Mandatory, ParameterSetName = 'new')][string]$New, 2 | [Parameter(Mandatory, ParameterSetName = 'remove')][string]$Remove) 3 | 4 | 5 | $tapDesc = 'TAP-Windows Adapter V9*' 6 | $tapDir = $env:ProgramFiles + "\TAP-Windows" 7 | $tapInstallCmd = "$tapDir\bin\tapinstall.exe" 8 | $tapInstallArgs = "install", "`"$tapDir\driver\OemVista.inf`"", "tap0901" # Backtick quotes https://stackoverflow.com/q/17550663 9 | 10 | if ($PSCmdlet.ParameterSetName -eq 'new') { 11 | if (Get-NetAdapter -InterfaceDescription $tapDesc | Where-Object Name -eq $New) { 12 | Write-Host "changed=no comment=`'TAP-Windows adapter $New exists`'" 13 | exit 14 | } 15 | if (-Not (Get-NetAdapter -InterfaceDescription $tapDesc | Where-Object Name -Match "^(Ethernet|Local Area Connection)")) { 16 | $p = Start-Process $tapInstallCmd -ArgumentList $tapInstallArgs -NoNewWindow -Wait -PassThru 17 | } 18 | Get-NetAdapter -InterfaceDescription $tapDesc | Where-Object Name -Match "^(Ethernet|Local Area Connection)" ` 19 | | Select-Object -First 1 | Rename-NetAdapter -NewName $New 20 | Write-Host "changed=yes comment=`'TAP-Windows adapter $New created`'" 21 | } 22 | 23 | if ($PSCmdlet.ParameterSetName -eq 'remove') { 24 | # No practical way to remove individual TAP adapter, so rename randomly to get it "out of the way" 25 | Get-NetAdapter -Name $Remove | Rename-NetAdapter -NewName "tmp$(Get-Random -Min 10 -Max 999)" 26 | Write-Host "changed=yes comment=`'TAP-Windows adapter $Remove removed`'" 27 | } 28 | 29 | -------------------------------------------------------------------------------- /openvpn/general_config.sls: -------------------------------------------------------------------------------- 1 | {# This SLS serves only as a capsule to ease handling of dependencies. #} 2 | 3 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 4 | 5 | {%- if map.manage_group is sameas false or map.user in ['nobody', 'nogroup'] %} 6 | {%- set manage_group = False %} 7 | {%- else %} 8 | {%- set manage_group = True %} 9 | openvpn_group: 10 | group.present: 11 | - name: {{ map.group }} 12 | - require_in: 13 | - file: openvpn_config_dir 14 | - sls: openvpn.config 15 | {%- endif %} 16 | 17 | {%- if not (map.manage_user is sameas false or map.user == 'nobody') %} 18 | openvpn_user: 19 | user.present: 20 | - name: {{ map.user }} 21 | - gid: {{ map.group }} 22 | {%- if manage_group %} 23 | - require: 24 | - group: openvpn_group 25 | {%- endif %} 26 | - require_in: 27 | - file: openvpn_config_dir 28 | - sls: openvpn.config 29 | {%- endif %} 30 | 31 | openvpn_config_dir: 32 | file.directory: 33 | - name: {{ map.conf_dir }} 34 | {%- if not grains['os_family'] == 'Windows' %} 35 | - mode: 750 36 | - user: {{ map.user }} 37 | - group: {{ map.group }} 38 | {%- endif %} 39 | - require_in: 40 | - sls: openvpn.config 41 | 42 | {%- if grains.os_family == 'FreeBSD' %} 43 | openvpn_kldload_if_tap: 44 | kmod.present: 45 | - name: if_tap 46 | - persist: True 47 | - require_in: 48 | - sls: openvpn.config 49 | {%- endif %} 50 | -------------------------------------------------------------------------------- /openvpn/gui.sls: -------------------------------------------------------------------------------- 1 | {% if salt['grains.get']('os_family') == 'Windows' %} 2 | 3 | # See https://github.com/OpenVPN/openvpn-gui 4 | {% set reg_values = { 'config_dir': 'REG_SZ', 5 | 'exe_path': 'REG_SZ', 6 | 'priority': 'REG_SZ', 7 | 'ovpn_admin_group': 'REG_SZ', 8 | 'disable_save_passwords': 'REG_DWORD'} %} 9 | 10 | {% for name, data in salt['pillar.get']('openvpn:gui', {}).items() %} 11 | {% if name in reg_values.keys() %} 12 | openvpn_gui_reg_{{ name }}: 13 | reg.present: 14 | - name: HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN 15 | - vname: {{ name }} 16 | - vdata: {{ data }} 17 | - vtype: {{ reg_values[name] }} 18 | {% endif %} 19 | {% endfor %} 20 | 21 | {% endif %} 22 | -------------------------------------------------------------------------------- /openvpn/hardening.sls: -------------------------------------------------------------------------------- 1 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 2 | 3 | include: 4 | - openvpn.config 5 | 6 | extend: 7 | {% for type, names in salt['pillar.get']('openvpn', {}).items() %} 8 | {% if type == 'server' or type == 'client' %} 9 | {% for name, config in names.items() %} 10 | {# hardening #} 11 | {% do config.update({'cipher': 'AES-256-CBC-HMAC-SHA1'}) %} 12 | {% do config.update({'tls-cipher': 'TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384'}) %} 13 | {% do config.update({'auth': 'SHA512'}) %} 14 | {% do config.update({'tls_version_min': '1.2'}) %} 15 | openvpn_config_{{ type }}_{{ name }}: 16 | file.managed: 17 | - context: 18 | name: {{ name }} 19 | config: {{ config }} 20 | user: {{ map.user }} 21 | group: {{ map.group }} 22 | 23 | {% endfor %} 24 | {% endif %} 25 | {% endfor %} 26 | -------------------------------------------------------------------------------- /openvpn/ifconfig_pool_persist.sls: -------------------------------------------------------------------------------- 1 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 2 | 3 | # deploy ifconfig_pool_persist files 4 | {%- for filename, config in salt['pillar.get']('openvpn', {}).get('ifconfig_pool_persist', {}).items() %} 5 | openvpn_config_ifconfig_pool_persist_{{ filename }}: 6 | file.managed: 7 | - name: {{ map.conf_dir }}/{{ filename }} 8 | - source: salt://openvpn/files/ifconfig_pool_persist.jinja 9 | - template: jinja 10 | - context: 11 | name: filename 12 | config: {{ config }} 13 | user: {{ map.user }} 14 | group: {{ map.group }} 15 | - watch_in: 16 | {% if salt['grains.has_value']('systemd') %} 17 | {% for type, names in salt['pillar.get']('openvpn', {}).items() %} 18 | {% if type in ['client', 'server', 'peer'] %} 19 | {% for name in names %} 20 | - service: openvpn_{{ name }}_service 21 | {% endfor %} 22 | {% endif %} 23 | {% endfor %} 24 | {% else %} 25 | - service: openvpn_service 26 | {% endif %} 27 | {%- endfor %} 28 | -------------------------------------------------------------------------------- /openvpn/init.sls: -------------------------------------------------------------------------------- 1 | # This is the main state file for configuring openvpn. 2 | 3 | include: 4 | - openvpn.repo 5 | - openvpn.install 6 | - openvpn.adapters 7 | - openvpn.dhparams 8 | - openvpn.service 9 | -------------------------------------------------------------------------------- /openvpn/install.sls: -------------------------------------------------------------------------------- 1 | {%- from "openvpn/map.jinja" import mapdata as map with context %} 2 | 3 | # Install openvpn packages 4 | openvpn_pkgs: 5 | {%- if salt['pillar.get']('openvpn:use_latest', False) %} 6 | pkg.latest: 7 | {% else %} 8 | pkg.installed: 9 | {% endif %} 10 | - pkgs: 11 | {%- for pkg in map.pkgs %} 12 | - {{ pkg }} 13 | {%- endfor %} 14 | 15 | {% if salt['grains.get']('os_family') == 'Windows' %} 16 | {% for cert_num in ['1', '2'] %} 17 | openvpn_publisher_cert_{{ cert_num }}: 18 | win_pki.import_cert: 19 | - name: salt://openvpn/files/openvpn-{{ cert_num }}.cer 20 | - store: TrustedPublisher 21 | - require_in: 22 | - pkg: openvpn_pkgs 23 | {% endfor %} 24 | {% endif %} 25 | -------------------------------------------------------------------------------- /openvpn/libmapstack.jinja: -------------------------------------------------------------------------------- 1 | {#- -*- coding: utf-8 -*- #} 2 | {#- vim: ft=jinja #} 3 | 4 | {#- Get the `tplroot` from `tpldir` #} 5 | {%- set tplroot = tpldir.split("/")[0] %} 6 | {%- from tplroot ~ "/libmatchers.jinja" import parse_matchers, query_map with context %} 7 | 8 | {%- set _default_config_dirs = [ 9 | "parameters/", 10 | tplroot ~ "/parameters" 11 | ] %} 12 | 13 | {%- macro mapstack( 14 | matchers, 15 | defaults=None, 16 | dirs=_default_config_dirs, 17 | log_prefix="libmapstack: " 18 | ) %} 19 | {#- 20 | Load configuration in the order of `matchers` and merge 21 | successively the values with `defaults`. 22 | 23 | The `matchers` are processed using `libmatchers.jinja` to select 24 | the configuration sources from where the values are loaded. 25 | 26 | Parameters: 27 | 28 | - `matchers`: list of matchers in the form 29 | `[[: