├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── ci.yml │ └── stale.yml ├── .gitignore ├── .markdownlint-cli2.yaml ├── .mdlrc ├── .overcommit.yml ├── .vscode └── extensions.json ├── .yamllint ├── Berksfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── LICENSE ├── README.md ├── TESTING.md ├── chefignore ├── documentation ├── .gitkeep ├── resolver_config.md └── resolver_systemd_resolved_config.md ├── kitchen.dokken.yml ├── kitchen.exec.yml ├── kitchen.global.yml ├── kitchen.yml ├── libraries ├── helpers.rb └── template.rb ├── metadata.rb ├── renovate.json ├── resources ├── config.rb └── systemd_resolved_config.rb ├── spec ├── spec_helper.rb └── unit │ └── resources │ ├── config_spec.rb │ └── systemd_resolved_config_spec.rb ├── templates └── default │ ├── 90-dns-none.conf.erb │ ├── resolv.conf.erb │ └── resolved.conf.erb └── test └── integration ├── cookbooks └── resolver-test │ ├── metadata.rb │ └── recipes │ ├── default.rb │ ├── systemd_resolved.rb │ └── test_packages.rb ├── default └── config_spec.rb └── systemd_resolved └── systemd_resolved_spec.rb /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root=true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 2 space indentation 12 | indent_style = space 13 | indent_size = 2 14 | 15 | # Avoid issues parsing cookbook files later 16 | charset = utf-8 17 | 18 | # Avoid cookstyle warnings 19 | trim_trailing_whitespace = true 20 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use chefworkstation 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sous-chefs/maintainers 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: ci 3 | 4 | "on": 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | lint-unit: 12 | uses: sous-chefs/.github/.github/workflows/lint-unit.yml@3.1.1 13 | permissions: 14 | actions: write 15 | checks: write 16 | pull-requests: write 17 | statuses: write 18 | issues: write 19 | 20 | integration: 21 | needs: lint-unit 22 | runs-on: ubuntu-latest 23 | strategy: 24 | matrix: 25 | os: 26 | - "almalinux-8" 27 | - "amazonlinux-2023" 28 | - "centos-7" 29 | - "centos-stream-8" 30 | - "debian-10" 31 | - "debian-11" 32 | - "fedora-latest" 33 | - "opensuse-leap-15" 34 | - "rockylinux-8" 35 | - "ubuntu-1804" 36 | - "ubuntu-2004" 37 | - "ubuntu-2204" 38 | suite: 39 | - "default" 40 | include: 41 | - suite: "systemd-resolved" 42 | os: "fedora-latest" 43 | - suite: "systemd-resolved" 44 | os: "ubuntu-1804" 45 | - suite: "systemd-resolved" 46 | os: "ubuntu-2004" 47 | - suite: "systemd-resolved" 48 | os: "ubuntu-2204" 49 | fail-fast: false 50 | 51 | steps: 52 | - name: Check out code 53 | uses: actions/checkout@v4 # v4 54 | - name: Install Chef 55 | uses: actionshub/chef-install@3.0.0 56 | - name: Dokken 57 | uses: actionshub/test-kitchen@3.0.0 58 | env: 59 | CHEF_LICENSE: accept-no-persist 60 | KITCHEN_LOCAL_YAML: kitchen.dokken.yml 61 | with: 62 | suite: ${{ matrix.suite }} 63 | os: ${{ matrix.os }} 64 | 65 | integration-macos: 66 | needs: lint-unit 67 | runs-on: macos-latest 68 | strategy: 69 | matrix: 70 | os: 71 | - "macos-latest" 72 | suite: 73 | - "default" 74 | fail-fast: false 75 | 76 | steps: 77 | - name: Check out code 78 | uses: actions/checkout@v4 # v4 79 | - name: Install Chef 80 | uses: actionshub/chef-install@3.0.0 81 | - name: test-kitchen 82 | uses: actionshub/test-kitchen@3.0.0 83 | env: 84 | CHEF_LICENSE: accept-no-persist 85 | KITCHEN_LOCAL_YAML: kitchen.exec.yml 86 | with: 87 | suite: ${{ matrix.suite }} 88 | os: ${{ matrix.os }} 89 | # TODO: This is currently broken unrelated to this cookbook 90 | # integration-freebsd: 91 | # needs: lint-unit 92 | # runs-on: macos-latest 93 | # strategy: 94 | # matrix: 95 | # os: 96 | # - "freebsd-12" 97 | # - "freebsd-13" 98 | # suite: 99 | # - "default" 100 | # fail-fast: false 101 | # 102 | # steps: 103 | # - name: Check out code 104 | # uses: actions/checkout@v3 105 | # - name: Install Chef 106 | # uses: actionshub/chef-install@2.0.4 107 | # - name: test-kitchen 108 | # uses: actionshub/test-kitchen@2.1.0 109 | # env: 110 | # KITCHEN_LOCAL_YAML: kitchen.yml 111 | # CHEF_LICENSE: accept-no-persist 112 | # with: 113 | # suite: ${{ matrix.suite }} 114 | # os: ${{ matrix.os }} 115 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mark stale issues and pull requests 3 | 4 | "on": 5 | schedule: [cron: "0 0 * * *"] 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v9 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | close-issue-message: > 15 | Closing due to inactivity. 16 | If this is still an issue please reopen or open another issue. 17 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 18 | Thanks, Sous-Chefs. 19 | days-before-close: 7 20 | days-before-stale: 365 21 | stale-issue-message: > 22 | Marking stale due to inactivity. 23 | Remove stale label or comment or this will be closed in 7 days. 24 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 25 | Thanks, Sous-Chefs. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | .config 3 | InstalledFiles 4 | pkg 5 | test/tmp 6 | test/version_tmp 7 | tmp 8 | _Store 9 | *~ 10 | *# 11 | .#* 12 | \#*# 13 | *.un~ 14 | *.tmp 15 | *.bk 16 | *.bkup 17 | 18 | # editor files 19 | .idea 20 | .*.sw[a-z] 21 | 22 | # ruby/bundler/rspec files 23 | .ruby-version 24 | .ruby-gemset 25 | .rvmrc 26 | Gemfile.lock 27 | .bundle 28 | *.gem 29 | coverage 30 | spec/reports 31 | 32 | # YARD / rdoc artifacts 33 | .yardoc 34 | _yardoc 35 | doc/ 36 | rdoc 37 | 38 | # chef infra stuff 39 | Berksfile.lock 40 | .kitchen 41 | kitchen.local.yml 42 | vendor/ 43 | .coverage/ 44 | .zero-knife.rb 45 | Policyfile.lock.json 46 | 47 | # vagrant stuff 48 | .vagrant/ 49 | .vagrant.d/ 50 | -------------------------------------------------------------------------------- /.markdownlint-cli2.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | ul-indent: false # MD007 3 | line-length: false # MD013 4 | no-duplicate-heading: false # MD024 5 | reference-links-images: false # MD052 6 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | rules "~MD013", "~MD024", "~MD025" 2 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | PreCommit: 3 | TrailingWhitespace: 4 | enabled: true 5 | YamlLint: 6 | enabled: true 7 | required_executable: "yamllint" 8 | ChefSpec: 9 | enabled: true 10 | required_executable: "chef" 11 | command: ["chef", "exec", "rspec"] 12 | Cookstyle: 13 | enabled: true 14 | required_executable: "cookstyle" 15 | command: ["cookstyle"] 16 | MarkdownLint: 17 | enabled: false 18 | required_executable: "npx" 19 | command: ["npx", "markdownlint-cli2", "'**/*.md'"] 20 | include: ["**/*.md"] 21 | 22 | CommitMsg: 23 | HardTabs: 24 | enabled: true 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "chef-software.chef", 4 | "rebornix.ruby", 5 | "editorconfig.editorconfig", 6 | "DavidAnson.vscode-markdownlint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | line-length: 5 | max: 256 6 | level: warning 7 | document-start: disable 8 | braces: 9 | forbid: false 10 | min-spaces-inside: 0 11 | max-spaces-inside: 1 12 | min-spaces-inside-empty: -1 13 | max-spaces-inside-empty: -1 14 | comments: 15 | min-spaces-from-content: 1 16 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | cookbook 'resolver-test', path: './test/integration/cookbooks/resolver-test' 4 | 5 | metadata 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # resolver Cookbook CHANGELOG 2 | 3 | This file is used to list changes made in each version of the resolver cookbook. 4 | 5 | ## Unreleased 6 | 7 | ## 4.2.2 - *2024-05-02* 8 | 9 | ## 4.2.1 - *2024-05-02* 10 | 11 | ## 4.2.0 - *2024-01-29* 12 | 13 | - Added support for sortlist option in resolv.conf 14 | 15 | ## 4.1.6 - *2023-12-21* 16 | 17 | ## 4.1.5 - *2023-10-03* 18 | 19 | ## 4.1.4 - *2023-09-29* 20 | 21 | ## 4.1.3 - *2023-05-17* 22 | 23 | ## 4.1.2 - *2023-05-04* 24 | 25 | - chore(deps): update actions/checkout action to v3 26 | 27 | ## 4.1.1 - *2023-05-03* 28 | 29 | - Update standardfiles 30 | 31 | ## 4.1.0 - *2022-08-08* 32 | 33 | - Remove delivery and move to calling RSpec directly via a reusable workflow 34 | - Add the `atomic_update` property 35 | - Use MacOS 10.15 when using Vagrant testing 36 | - Update Linux platforms for testing 37 | 38 | ## 4.0.3 - *2022-02-08* 39 | 40 | - Remove delivery folder 41 | 42 | ## 4.0.2 - *2021-08-30* 43 | 44 | - Standardise files with files in sous-chefs/repo-management 45 | 46 | ## 4.0.1 - *2021-06-01* 47 | 48 | - Standardise files with files in sous-chefs/repo-management 49 | 50 | ## 4.0.0 - *2021-05-26* 51 | 52 | - Switch to `unified_mode` 53 | - Update `chef_version` to only support Chef 15.3 or later 54 | 55 | ## 3.0.4 - *2021-03-03* 56 | 57 | - Fixed typo in the `CacheFromLocalhost` parameter in the systemd-resolved template 58 | 59 | ## 3.0.3 - *2021-02-25* 60 | 61 | - Fix blog link for wrapper cookbooks 62 | 63 | ## 3.0.2 - *2021-02-25* 64 | 65 | - Merge resolv.conf options & remove extra colons 66 | 67 | ## 3.0.1 - *2021-02-20* 68 | 69 | - Update `Chef` -> `Chef Infra` 70 | 71 | ## 3.0.0 - *2021-02-18* 72 | 73 | - Port recipes and attributes to resources 74 | - Add support for overriding system configuration methods to resolver_config 75 | - Add systemd-resolved support 76 | 77 | ## 2.2.0 - *2021-02-10* 78 | 79 | - Sous Chefs Adoption 80 | - Add InSpec Tests 81 | - Remove Deprecated Platforms, Centos 6, Ubuntu 16.04, opensuse-42, fedora-29 82 | 83 | ## 2.1.0 (2018-07-18) 84 | 85 | - Test with Local Delivery instead of Rake 86 | - Update Apache license string in metadata 87 | - the search stanza should be an array rather than a single element. resolv.conf search allows up to six search domains to be defined. Have updated the recipes with some rules (no more than 6 domains or 256 chars), change the ['resolver']['search'] into an array and changed teh template unless block to search for an empty array instead 88 | - add aix support 89 | 90 | ## 2.0.1 (2017-02-24) 91 | 92 | - Fix compatibility with old chef 12 clients 93 | - Remove old recipe from the metadata 94 | - Call out SUSE support in the readme and metadata 95 | 96 | ## 2.0.0 (2016-09-07) 97 | 98 | - add support for 'domain' resolv.conf key 99 | - Switch to root group to support AIX/OS X/FreeBSD 100 | - Removed the from_server_role recipe. This should be done with a wrapper cookbook instead 101 | - Add testing with Travis CI and use kitchen-dokken for integration testing 102 | - Add basic Chefspec testing 103 | - Add integration testing with Test Kitchen 104 | - Add Berksfile 105 | - Update contributing, testing and maintainers docs 106 | - Improve the readme with chef/platform Requirements 107 | - Add a Rakefile for simplified testing 108 | - Use strings for file modes to preserve the leading 0s 109 | - Add source_url, issue_url and chef_version to the metadata 110 | - Remove attributes from the metadata since they weren't up to date 111 | 112 | ## v1.3.0 (2015-10-16) 113 | 114 | - Add rubocop file and resolve all rubocop warnings 115 | - Update the contributing doc to match the new process 116 | - Use strings for file modes to preserve the leading 0s 117 | - Add support the domain resolv.conf config option 118 | - Add a gitignore and chefignore file 119 | - Added a header to the resolv.conf file stating that chef edited the file 120 | - Use the Ohai 'root_group' attribute for the config file to support non-Linux *nix platforms. This raises the minimum required version of Chef to 11.14.0 with Ohai 7.2.0. 121 | 122 | ## v1.2.0 (2014-10-16) 123 | 124 | - [#11] Improve safety and sanity of cookbook 125 | - [#12] README update 126 | - [#14] Exclude search in template if attribute is empty 127 | 128 | ## v1.1.4 129 | 130 | - [COOK-3375] - Add Solaris support 131 | 132 | ## v1.1.2 133 | 134 | ### Bug 135 | 136 | - [COOK-2977]: resolver cookbook has foodcritic failures 137 | 138 | ## v1.1.0 139 | 140 | - [COOK-1242] - collect nameservers using a server role, adds `from_server_role` recipe 141 | 142 | ## v1.0.2 143 | 144 | - 'node' went missing in the template. 145 | 146 | ## v1.0.0 147 | 148 | - [COOK-1089] - accept resolver options via attributes 149 | - [COOK-1109] - return from resolver recipe if no nameserver attribute is set so resolv.conf doesn't get broken during the run 150 | - [COOK-1150] - drop the empty element from the nameserver attribute array 151 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Guidelines 2 | 3 | This project follows the Chef Community Guidelines 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please refer to 4 | [https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) 5 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Reference: http://danger.systems/reference.html 2 | 3 | # A pull request summary is required. Add a description of the pull request purpose. 4 | # Changelog must be updated for each pull request that changes code. 5 | # Warnings will be issued for: 6 | # Pull request with more than 400 lines of code changed 7 | # Pull reqest that change more than 5 lines without test changes 8 | # Failures will be issued for: 9 | # Pull request without summary 10 | # Pull requests with code changes without changelog entry 11 | 12 | def code_changes? 13 | code = %w(libraries attributes recipes resources files templates) 14 | code.each do |location| 15 | return true unless git.modified_files.grep(/#{location}/).empty? 16 | end 17 | false 18 | end 19 | 20 | def test_changes? 21 | tests = %w(spec test kitchen.yml kitchen.dokken.yml) 22 | tests.each do |location| 23 | return true unless git.modified_files.grep(/#{location}/).empty? 24 | end 25 | false 26 | end 27 | 28 | failure 'Please provide a summary of your Pull Request.' if github.pr_body.length < 10 29 | 30 | warn 'This is a big Pull Request.' if git.lines_of_code > 400 31 | 32 | warn 'This is a Table Flip.' if git.lines_of_code > 2000 33 | 34 | # Require a CHANGELOG entry for non-test changes. 35 | if !git.modified_files.include?('CHANGELOG.md') && code_changes? 36 | failure 'Please include a CHANGELOG entry.' 37 | end 38 | 39 | # Require Major Minor Patch version labels 40 | unless github.pr_labels.grep /minor|major|patch/i 41 | warn 'Please add a release label to this pull request' 42 | end 43 | 44 | # A sanity check for tests. 45 | if git.lines_of_code > 5 && code_changes? && !test_changes? 46 | warn 'This Pull Request is probably missing tests.' 47 | end 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # resolver Cookbook 2 | 3 | [![Cookbook Version](https://img.shields.io/cookbook/v/resolver.svg)](https://supermarket.chef.io/cookbooks/resolver) 4 | [![CI State](https://github.com/sous-chefs/resolver/workflows/ci/badge.svg)](https://github.com/sous-chefs/resolver/actions?query=workflow%3Aci) 5 | [![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers) 6 | [![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors) 7 | [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) 8 | 9 | Configures /etc/resolv.conf, unless the nameservers attribute is empty. Search will be excluded if empty. 10 | 11 | ## Maintainers 12 | 13 | This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If you’d like to know more please visit sous-chefs.org or come chat with us on the Chef Community Slack in #sous-chefs. 14 | 15 | ## Requirements 16 | 17 | ### Platforms 18 | 19 | - AIX 20 | - Debian/Ubuntu 21 | - RHEL/CentOS/Scientific/Amazon/Oracle 22 | - Fedora 23 | - FreeBSD/OpenBSD 24 | - macOS 25 | - Solaris 26 | - openSUSE / SUSE Enterprise 27 | 28 | ### Chef 29 | 30 | - Chef 15.3+ 31 | 32 | ## Resources 33 | 34 | - [resolver_config](documentation/resolver_config.md) 35 | - [resolver_systemd_resolved_config](documentation/resolver_systemd_resolved_config.md) 36 | 37 | ## Usage 38 | 39 | It is recommended to create a project or organization specific [wrapper cookbook](https://blog.chef.io/doing-wrapper-cookbooks-right) and add the desired custom resources to the run list of a node. 40 | 41 | Example of configuring a node with nameservers, a search list and a local domain. 42 | 43 | ```ruby 44 | resolver_config '/etc/resolv.conf' do 45 | nameservers ['1.1.1.1', '1.0.0.1'] 46 | domain 'test.com' 47 | search ['test1.com', 'test2.com'] 48 | options( 49 | 'timeout' => 2 50 | ) 51 | end 52 | ``` 53 | 54 | The resulting `/etc/resolv.conf` will look like: 55 | 56 | ```text 57 | # 58 | # Generated by Chef Infra for dokken 59 | # Do NOT modify this file by hand, changes will be overwritten. 60 | # 61 | 62 | domain test.com 63 | search test1.com test2.com 64 | nameserver 1.1.1.1 65 | nameserver 1.0.0.1 66 | options timeout:2 67 | ``` 68 | 69 | ## Contributors 70 | 71 | This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false) 72 | 73 | ### Backers 74 | 75 | Thank you to all our backers! 76 | 77 | ![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40) 78 | 79 | ### Sponsors 80 | 81 | Support this project by becoming a sponsor. Your logo will show up here with a link to your website. 82 | 83 | ![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100) 84 | ![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100) 85 | ![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100) 86 | ![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100) 87 | ![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100) 88 | ![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100) 89 | ![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100) 90 | ![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100) 91 | ![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100) 92 | ![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100) 93 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Please refer to [the community cookbook documentation on testing](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/TESTING.MD). 4 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # to a Chef Infra Server or Supermarket. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | ehthumbs.db 9 | Icon? 10 | nohup.out 11 | Thumbs.db 12 | .envrc 13 | 14 | # EDITORS # 15 | ########### 16 | .#* 17 | .project 18 | .settings 19 | *_flymake 20 | *_flymake.* 21 | *.bak 22 | *.sw[a-z] 23 | *.tmproj 24 | *~ 25 | \#* 26 | REVISION 27 | TAGS* 28 | tmtags 29 | .vscode 30 | .editorconfig 31 | 32 | ## COMPILED ## 33 | ############## 34 | *.class 35 | *.com 36 | *.dll 37 | *.exe 38 | *.o 39 | *.pyc 40 | *.so 41 | */rdoc/ 42 | a.out 43 | mkmf.log 44 | 45 | # Testing # 46 | ########### 47 | .circleci/* 48 | .codeclimate.yml 49 | .delivery/* 50 | .foodcritic 51 | .kitchen* 52 | .mdlrc 53 | .overcommit.yml 54 | .rspec 55 | .rubocop.yml 56 | .travis.yml 57 | .watchr 58 | .yamllint 59 | azure-pipelines.yml 60 | Dangerfile 61 | examples/* 62 | features/* 63 | Guardfile 64 | kitchen*.yml 65 | mlc_config.json 66 | Procfile 67 | Rakefile 68 | spec/* 69 | test/* 70 | 71 | # SCM # 72 | ####### 73 | .git 74 | .gitattributes 75 | .gitconfig 76 | .github/* 77 | .gitignore 78 | .gitkeep 79 | .gitmodules 80 | .svn 81 | */.bzr/* 82 | */.git 83 | */.hg/* 84 | */.svn/* 85 | 86 | # Berkshelf # 87 | ############# 88 | Berksfile 89 | Berksfile.lock 90 | cookbooks/* 91 | tmp 92 | 93 | # Bundler # 94 | ########### 95 | vendor/* 96 | Gemfile 97 | Gemfile.lock 98 | 99 | # Policyfile # 100 | ############## 101 | Policyfile.rb 102 | Policyfile.lock.json 103 | 104 | # Documentation # 105 | ############# 106 | CODE_OF_CONDUCT* 107 | CONTRIBUTING* 108 | documentation/* 109 | TESTING* 110 | UPGRADING* 111 | 112 | # Vagrant # 113 | ########### 114 | .vagrant 115 | Vagrantfile 116 | -------------------------------------------------------------------------------- /documentation/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sous-chefs/resolver/97ccab738995d649470b46278d95cbdb8fae6eb8/documentation/.gitkeep -------------------------------------------------------------------------------- /documentation/resolver_config.md: -------------------------------------------------------------------------------- 1 | # resolver_config 2 | 3 | [Back to resource list](../README.md#resources) 4 | 5 | Introduced: v3.0.0 6 | 7 | ## Actions 8 | 9 | - `:set` 10 | 11 | ## Properties 12 | 13 | | Name | Type | Default | Description | 14 | | ---------------------- | ------------- | -------------------------------- | --------------------------------------------------------------------------------| 15 | | `config_file` | String | `/etc/resolv.conf` | The path to the resolver configuration file on disk | 16 | | `cookbook` | String | `resolver` | Cookbook to source configuration file template from | 17 | | `template` | String | `resolv.conf.erb` | Template to use to generate the configuration file | 18 | | `owner` | String | Platform dependant | Owner of the generated configuration file | 19 | | `group` | String | Platform dependant | Group of the generated configuration file | 20 | | `mode` | String | `'0644'` | Filemode of the generated configuration file | 21 | | `nameservers` | String, Array | `nil` | The DNS servers to configure for system name resolution | 22 | | `domain` | String | `nil` | The DNS domain name for the host | 23 | | `search` | String, Array | `nil` | The DNS domain search list for the host | 24 | | `sortlist` | String, Array | `nil` | The DNS sort list for the host | 25 | | `options` | Hash | `nil` | Additional options to add to the resolver configuration file | 26 | | `atomic_update` | true, false | `true` | Allow to Ran atomic file update (Could be used when updating inside a container | 27 | 28 | ## Examples 29 | 30 | ```ruby 31 | resolver_config '/etc/resolv.conf' do 32 | nameservers ['1.1.1.1', '1.0.0.1'] 33 | domain 'test.com' 34 | search ['test1.com', 'test2.com'] 35 | options( 36 | 'timeout' => 2 37 | ) 38 | end 39 | ``` 40 | -------------------------------------------------------------------------------- /documentation/resolver_systemd_resolved_config.md: -------------------------------------------------------------------------------- 1 | # resolver_systemd_resolved_config 2 | 3 | [Back to resource list](../README.md#resources) 4 | 5 | Create and manage the systemd-resolved configuration file. () 6 | 7 | Introduced: v3.0.0 8 | 9 | ## Actions 10 | 11 | - `:set` 12 | 13 | ## Properties 14 | 15 | | Name | Type | Default | Description | 16 | | ---------------------- | ------------- | -------------------------------- | ------------------------------------------------------------------- | 17 | | `config_file` | String | `/etc/systemd/resolved.conf` | The path to the systemd-resolved configuration file on disk | 18 | | `cookbook` | String | `resolver` | Cookbook to source configuration file template from | 19 | | `template` | String | `resolved.conf.erb` | Template to use to generate the configuration file | 20 | | `owner` | String | Platform dependant | Owner of the generated configuration file | 21 | | `group` | String | Platform dependant | Group of the generated configuration file | 22 | | `mode` | String | `'0644'` | Filemode of the generated configuration file | 23 | | `dns` | String, Array | `nil` | A list of IPv4 and IPv6 addresses to use as system DNS servers | 24 | | `fallback_dns` | String, Array | `nil` | A list of IPv4 and IPv6 addresses to use as fallback DNS servers | 25 | | `domains` | String, Array | `nil` | A list of DNS search domains for the host | 26 | | `llmnr` | True, False, String | `nil` | Control Link-Local Multicast Name Resolution support (RFC 4795) on the host | 27 | | `multicast_dns` | True, False, String | `'resolve'` | Control Multicast DNS support (RFC 6762) on the host | 28 | | `dnssec` | True, False, String | `'allow-downgrade'` | Control DNSSEC validation on the host | 29 | | `dns_over_tls` | True, False, String | `'opportunistic'` | Control DNS-over-TLS on the host | 30 | | `cache` | True, False, String | `true` | Control DNS caching on the host | 31 | | `cache_from_localhost` | True, False | `false` | Control DNS caching of a result from a local address on the host | 32 | | `dns_stub_listener` | True, False, String | `nil` | Control the DNS stub listener on the host | 33 | | `dns_stub_listener_extra` | True, False, String | `nil` |Additional DNS stub sockets to listen on for the host | 34 | | `read_etc_hosts` | True, False | `true` | Control resolution of a hostname from the /etc/hosts file | 35 | | `resolve_unicast_single_label` | True, False | `false` | Control resolution of A and AAAA queries for single-label names over classic DNS | 36 | 37 | ## Examples 38 | 39 | ```ruby 40 | resolver_systemd_resolved_config '/etc/systemd/resolved.conf' do 41 | dns ['1.1.1.1', '1.0.0.1', '2606:4700:4700::1111', '2606:4700:4700::1001'] 42 | fallback_dns '8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844' 43 | domains 'localtest.com' 44 | end 45 | ``` 46 | -------------------------------------------------------------------------------- /kitchen.dokken.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: dokken 3 | privileged: true 4 | chef_version: <%= ENV['CHEF_VERSION'] || 'current' %> 5 | 6 | transport: { name: dokken } 7 | provisioner: { name: dokken } 8 | 9 | platforms: 10 | - name: almalinux-8 11 | driver: 12 | image: dokken/almalinux-8 13 | pid_one_command: /usr/lib/systemd/systemd 14 | 15 | - name: almalinux-9 16 | driver: 17 | image: dokken/almalinux-9 18 | pid_one_command: /usr/lib/systemd/systemd 19 | 20 | - name: amazonlinux-2023 21 | driver: 22 | image: dokken/amazonlinux-2023 23 | pid_one_command: /usr/lib/systemd/systemd 24 | 25 | - name: centos-7 26 | driver: 27 | image: dokken/centos-7 28 | pid_one_command: /usr/lib/systemd/systemd 29 | 30 | - name: centos-stream-8 31 | driver: 32 | image: dokken/centos-stream-8 33 | pid_one_command: /usr/lib/systemd/systemd 34 | 35 | - name: centos-stream-9 36 | driver: 37 | image: dokken/centos-stream-9 38 | pid_one_command: /usr/lib/systemd/systemd 39 | 40 | - name: debian-9 41 | driver: 42 | image: dokken/debian-9 43 | pid_one_command: /bin/systemd 44 | 45 | - name: debian-10 46 | driver: 47 | image: dokken/debian-10 48 | pid_one_command: /bin/systemd 49 | 50 | - name: debian-11 51 | driver: 52 | image: dokken/debian-11 53 | pid_one_command: /bin/systemd 54 | 55 | - name: debian-12 56 | driver: 57 | image: dokken/debian-12 58 | pid_one_command: /bin/systemd 59 | 60 | - name: fedora-latest 61 | driver: 62 | image: dokken/fedora-latest 63 | pid_one_command: /usr/lib/systemd/systemd 64 | 65 | - name: opensuse-leap-15 66 | driver: 67 | image: dokken/opensuse-leap-15 68 | pid_one_command: /usr/lib/systemd/systemd 69 | 70 | - name: oraclelinux-7 71 | driver: 72 | image: dokken/oraclelinux-7 73 | pid_one_command: /usr/lib/systemd/systemd 74 | 75 | - name: oraclelinux-8 76 | driver: 77 | image: dokken/oraclelinux-8 78 | pid_one_command: /usr/lib/systemd/systemd 79 | 80 | - name: oraclelinux-9 81 | driver: 82 | image: dokken/oraclelinux-9 83 | pid_one_command: /usr/lib/systemd/systemd 84 | 85 | - name: rockylinux-8 86 | driver: 87 | image: dokken/rockylinux-8 88 | pid_one_command: /usr/lib/systemd/systemd 89 | 90 | - name: rockylinux-9 91 | driver: 92 | image: dokken/rockylinux-9 93 | pid_one_command: /usr/lib/systemd/systemd 94 | 95 | - name: ubuntu-18.04 96 | driver: 97 | image: dokken/ubuntu-18.04 98 | pid_one_command: /bin/systemd 99 | 100 | - name: ubuntu-20.04 101 | driver: 102 | image: dokken/ubuntu-20.04 103 | pid_one_command: /bin/systemd 104 | 105 | - name: ubuntu-22.04 106 | driver: 107 | image: dokken/ubuntu-22.04 108 | pid_one_command: /bin/systemd 109 | 110 | - name: ubuntu-23.04 111 | driver: 112 | image: dokken/ubuntu-23.04 113 | pid_one_command: /bin/systemd 114 | -------------------------------------------------------------------------------- /kitchen.exec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: { name: exec } 3 | transport: { name: exec } 4 | 5 | platforms: 6 | - name: macos-latest 7 | - name: windows-latest 8 | -------------------------------------------------------------------------------- /kitchen.global.yml: -------------------------------------------------------------------------------- 1 | --- 2 | provisioner: 3 | name: chef_infra 4 | product_name: chef 5 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 6 | channel: stable 7 | install_strategy: once 8 | chef_license: accept 9 | enforce_idempotency: <%= ENV['ENFORCE_IDEMPOTENCY'] || true %> 10 | multiple_converge: <%= ENV['MULTIPLE_CONVERGE'] || 2 %> 11 | deprecations_as_errors: true 12 | log_level: <%= ENV['CHEF_LOG_LEVEL'] || 'auto' %> 13 | 14 | verifier: 15 | name: inspec 16 | 17 | platforms: 18 | - name: almalinux-8 19 | - name: almalinux-9 20 | - name: amazonlinux-2023 21 | - name: centos-7 22 | - name: centos-stream-8 23 | - name: centos-stream-9 24 | - name: debian-9 25 | - name: debian-10 26 | - name: debian-11 27 | - name: debian-12 28 | - name: fedora-latest 29 | - name: opensuse-leap-15 30 | - name: oraclelinux-7 31 | - name: oraclelinux-8 32 | - name: oraclelinux-9 33 | - name: rockylinux-8 34 | - name: rockylinux-9 35 | - name: ubuntu-18.04 36 | - name: ubuntu-20.04 37 | - name: ubuntu-22.04 38 | - name: ubuntu-23.04 39 | -------------------------------------------------------------------------------- /kitchen.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: vagrant 3 | 4 | provisioner: 5 | name: chef_zero 6 | deprecations_as_errors: true 7 | chef_license: accept-no-persist 8 | 9 | verifier: 10 | name: inspec 11 | 12 | platforms: 13 | - name: amazonlinux-2 14 | - name: centos-7 15 | - name: centos-8 16 | - name: debian-10 17 | - name: debian-9 18 | - name: fedora-latest 19 | - name: freebsd-12 20 | - name: freebsd-13 21 | - name: ubuntu-18.04 22 | - name: ubuntu-20.04 23 | 24 | suites: 25 | - name: default 26 | run_list: 27 | - recipe[resolver-test::test_packages] 28 | - recipe[resolver-test::default] 29 | - name: systemd_resolved 30 | run_list: 31 | - recipe[resolver-test::test_packages] 32 | - recipe[resolver-test::systemd_resolved] 33 | includes: 34 | - fedora-latest 35 | - ubuntu-18.04 36 | - ubuntu-20.04 37 | - ubuntu-22.04 38 | verifier: 39 | inspec_tests: 40 | - test/integration/systemd_resolved 41 | -------------------------------------------------------------------------------- /libraries/helpers.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | 3 | module Resolver 4 | module Cookbook 5 | module Helpers 6 | RESOLVER_RESOLV_CONF_DEFAULT = '/etc/resolv.conf'.freeze 7 | RESOLVER_RESOLVED_CONF_DEFAULT = '/etc/systemd/resolved.conf'.freeze 8 | RESOLVER_CONF_USER_DEFAULT = 'root'.freeze 9 | 10 | def resolver_conf_group_default 11 | node['root_group'] 12 | end 13 | 14 | def resolver_override_default(file) 15 | return false if Pathname.new(file).mountpoint? 16 | 17 | true 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /libraries/template.rb: -------------------------------------------------------------------------------- 1 | module Resolver 2 | module Cookbook 3 | module TemplateHelpers 4 | def nil_or_empty?(property) 5 | property.nil? || (property.respond_to?(:empty?) && property.empty?) 6 | end 7 | 8 | def systemd_value(value) 9 | case value 10 | when true 11 | 'yes' 12 | when false 13 | 'no' 14 | else 15 | value 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'resolver' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | license 'Apache-2.0' 5 | description 'Configures /etc/resolv.conf via attributes' 6 | version '4.2.2' 7 | source_url 'https://github.com/sous-chefs/resolver' 8 | issues_url 'https://github.com/sous-chefs/resolver/issues' 9 | chef_version '>= 15.3' 10 | 11 | supports 'amazon' 12 | supports 'centos' 13 | supports 'debian' 14 | supports 'fedora' 15 | supports 'freebsd' 16 | supports 'mac_os_x' 17 | supports 'openbsd' 18 | supports 'opensuse' 19 | supports 'opensuseleap' 20 | supports 'oracle' 21 | supports 'redhat' 22 | supports 'scientific' 23 | supports 'solaris2' 24 | supports 'suse' 25 | supports 'ubuntu' 26 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "groupName": "Actions", 7 | "matchUpdateTypes": ["minor", "patch", "pin"], 8 | "automerge": true, 9 | "addLabels": ["Release: Patch", "Skip: Announcements"] 10 | }, 11 | { 12 | "groupName": "Actions", 13 | "matchUpdateTypes": ["major"], 14 | "automerge": false, 15 | "addLabels": ["Release: Patch", "Skip: Announcements"] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /resources/config.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: resolver 3 | # Resource:: config 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | unified_mode true 19 | 20 | include Resolver::Cookbook::Helpers 21 | 22 | property :config_file, String, 23 | default: lazy { RESOLVER_RESOLV_CONF_DEFAULT }, 24 | description: 'The path to the resolver configuration file on disk' 25 | 26 | property :cookbook, String, 27 | default: 'resolver', 28 | description: 'Template source cookbook' 29 | 30 | property :template, String, 31 | default: 'resolv.conf.erb', 32 | description: 'Template source file' 33 | 34 | property :owner, String, 35 | default: lazy { RESOLVER_CONF_USER_DEFAULT }, 36 | description: 'Generated file owner' 37 | 38 | property :group, String, 39 | default: lazy { resolver_conf_group_default }, 40 | description: 'Generated file group' 41 | 42 | property :mode, String, 43 | default: '0644', 44 | description: 'Generated file mode' 45 | 46 | property :nameservers, [String, Array], 47 | coerce: proc { |p| p.is_a?(String) ? p.split(',') : p }, 48 | required: true, 49 | description: 'The DNS servers to configure for system name resolution' 50 | 51 | property :domain, String, 52 | description: 'The DNS domain name for the host' 53 | 54 | property :search, [String, Array], 55 | coerce: proc { |p| p.is_a?(String) ? p.split(',') : p }, 56 | description: 'The DNS domain search list for the host', 57 | callbacks: { 58 | 'with glibc < 2.26 the number of search domains are limited to 6' => lambda { |p| 59 | p.count <= 6 || (node['languages']['c']['glibc']['version'].to_f >= 2.26) 60 | }, 61 | 'with glibc < 2.26 the total length of the search list is limited to 256 character' => lambda { |p| 62 | p.join(' ').length <= 256 || (node['languages']['c']['glibc']['version'].to_f >= 2.26) 63 | }, 64 | } 65 | 66 | property :sortlist, [String, Array], 67 | coerce: proc { |p| p.is_a?(Array) ? p : [p] }, 68 | description: 'The DNS sort list for the host' 69 | 70 | property :options, Hash, 71 | description: 'Additional options to add to the resolver configuration file' 72 | 73 | property :atomic_update, [true, false], 74 | default: true, 75 | description: 'Perform atomic file updates on a per-resource basis' 76 | 77 | property :override_system_configuration, [true, false], 78 | default: lazy { resolver_override_default(config_file) }, 79 | description: 'Override the system DNS configuration, for use with NetworkManager/resolvconf/systemd-resolved' 80 | 81 | action :set do 82 | if new_resource.override_system_configuration 83 | directory '/etc/NetworkManager/conf.d' do 84 | recursive true 85 | end 86 | 87 | template '/etc/NetworkManager/conf.d/90-dns-none.conf' do 88 | cookbook new_resource.cookbook 89 | source '90-dns-none.conf.erb' 90 | 91 | owner new_resource.owner 92 | group new_resource.group 93 | mode new_resource.mode 94 | 95 | action :create 96 | end if ::Dir.exist?('/etc/NetworkManager') 97 | end 98 | 99 | template new_resource.config_file do 100 | cookbook new_resource.cookbook 101 | source new_resource.template 102 | 103 | owner new_resource.owner 104 | group new_resource.group 105 | mode new_resource.mode 106 | 107 | force_unlink new_resource.override_system_configuration 108 | manage_symlink_source !new_resource.override_system_configuration 109 | 110 | atomic_update new_resource.atomic_update 111 | 112 | variables( 113 | nameservers: new_resource.nameservers, 114 | domain: new_resource.domain, 115 | search: new_resource.search, 116 | sortlist: new_resource.sortlist, 117 | options: new_resource.options 118 | ) 119 | helpers(Resolver::Cookbook::TemplateHelpers) 120 | 121 | action :create 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /resources/systemd_resolved_config.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: resolver 3 | # Resource:: config 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | unified_mode true 19 | 20 | include Resolver::Cookbook::Helpers 21 | 22 | property :config_file, String, 23 | default: lazy { RESOLVER_RESOLVED_CONF_DEFAULT }, 24 | description: 'The path to the systemd-resolved configuration file on disk' 25 | 26 | property :cookbook, String, 27 | default: 'resolver', 28 | description: 'Template source cookbook' 29 | 30 | property :template, String, 31 | default: 'resolved.conf.erb', 32 | description: 'Template source file' 33 | 34 | property :owner, String, 35 | default: lazy { RESOLVER_CONF_USER_DEFAULT }, 36 | description: 'Generated file owner' 37 | 38 | property :group, String, 39 | default: lazy { resolver_conf_group_default }, 40 | description: 'Generated file group' 41 | 42 | property :mode, String, 43 | default: '0644', 44 | description: 'Generated file mode' 45 | 46 | property :dns, [String, Array], 47 | coerce: proc { |p| p.is_a?(String) ? p.split(',').each(&:strip) : p }, 48 | required: true, 49 | description: 'A list of IPv4 and IPv6 addresses to use as system DNS servers' 50 | 51 | property :fallback_dns, [String, Array], 52 | coerce: proc { |p| p.is_a?(String) ? p.split(',').each(&:strip) : p }, 53 | description: 'A list of IPv4 and IPv6 addresses to use as fallback DNS servers' 54 | 55 | property :domains, [String, Array], 56 | coerce: proc { |p| p.is_a?(String) ? p.split(',').each(&:strip) : p }, 57 | description: 'A list of DNS search domains for the host' 58 | 59 | property :llmnr, [true, false, String], 60 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 61 | equal_to: [true, false, 'resolve'], 62 | description: 'Control Link-Local Multicast Name Resolution support (RFC 4795) on the host' 63 | 64 | property :multicast_dns, [true, false, String], 65 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 66 | equal_to: [true, false, 'resolve'], 67 | description: 'Control Multicast DNS support (RFC 6762) on the host' 68 | 69 | property :dnssec, [true, false, String], 70 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 71 | default: 'allow-downgrade', 72 | equal_to: [true, false, 'allow-downgrade'], 73 | description: 'Control DNSSEC validation on the host' 74 | 75 | property :dns_over_tls, [true, false, String], 76 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 77 | default: false, 78 | equal_to: [true, false, 'opportunistic'], 79 | description: 'Control DNS-over-TLS on the host' 80 | 81 | property :cache, [true, false, String], 82 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 83 | default: true, 84 | equal_to: [true, false, 'no-negative'], 85 | description: 'Control DNS caching on the host' 86 | 87 | property :cache_from_localhost, [true, false], 88 | default: false, 89 | description: 'Control DNS caching of a result from a local address on the host' 90 | 91 | property :dns_stub_listener, [true, false, String], 92 | coerce: proc { |p| p.is_a?(String) ? p.downcase : p }, 93 | equal_to: [true, false, 'udp', 'tcp'], 94 | description: 'Control the DNS stub listener on the host' 95 | 96 | property :dns_stub_listener_extra, [String, Array], 97 | coerce: proc { |p| p.is_a?(String) ? p.split(',') : p }, 98 | description: 'Additional DNS stub sockets to listen on for the host' 99 | 100 | property :read_etc_hosts, [true, false], 101 | default: true, 102 | description: 'Control resolution of a hostname from the /etc/hosts file' 103 | 104 | property :resolve_unicast_single_label, [true, false], 105 | default: false, 106 | description: 'Control resolution of A and AAAA queries for single-label names over classic DNS' 107 | 108 | action :set do 109 | template new_resource.config_file do 110 | cookbook new_resource.cookbook 111 | source new_resource.template 112 | 113 | owner new_resource.owner 114 | group new_resource.group 115 | mode new_resource.mode 116 | 117 | variables( 118 | dns: new_resource.dns, 119 | fallbackdns: new_resource.fallback_dns, 120 | domains: new_resource.domains, 121 | llmnr: new_resource.llmnr, 122 | multicastdns: new_resource.multicast_dns, 123 | dnssec: new_resource.dnssec, 124 | dnsovertls: new_resource.dns_over_tls, 125 | cache: new_resource.cache, 126 | cachefromlocalhost: new_resource.cache_from_localhost, 127 | dnsstublistener: new_resource.dns_stub_listener, 128 | dnsstublistenerextra: new_resource.dns_stub_listener_extra, 129 | readetchosts: new_resource.read_etc_hosts, 130 | resolveunicastsinglelabel: new_resource.resolve_unicast_single_label 131 | ) 132 | helpers(Resolver::Cookbook::TemplateHelpers) 133 | 134 | notifies :restart, 'service[systemd-resolved]', :delayed 135 | 136 | action :create 137 | end 138 | 139 | service 'systemd-resolved' do 140 | action :nothing 141 | end 142 | end 143 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | 4 | RSpec.configure do |config| 5 | config.color = true # Use color in STDOUT 6 | config.formatter = :documentation # Use the specified formatter 7 | config.log_level = :error # Avoid deprecation notice SPAM 8 | end 9 | -------------------------------------------------------------------------------- /spec/unit/resources/config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'resolver_config' do 4 | step_into :resolver_config 5 | platform 'centos' 6 | 7 | context 'create a resolv config and verify config is created properly' do 8 | recipe do 9 | resolver_config '/etc/resolv.conf' do 10 | nameservers ['1.1.1.1', '1.0.0.1'] 11 | domain 'test.com' 12 | search ['test1.com', 'test2.com'] 13 | options( 14 | 'timeout' => 2, 15 | 'rotate' => nil, 16 | 'attempts' => 1 17 | ) 18 | end 19 | end 20 | 21 | it 'Creates the main configuration file' do 22 | is_expected.to render_file('/etc/resolv.conf') 23 | .with_content(/nameserver 1.1.1.1/) 24 | .with_content(/nameserver 1.0.0.1/) 25 | .with_content(/domain test\.com/) 26 | .with_content(/search test1\.com test2\.com/) 27 | .with_content(/options timeout:2 rotate attempts:1/) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/unit/resources/systemd_resolved_config_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'resolver_systemd_resolved_config' do 4 | step_into :resolver_systemd_resolved_config 5 | platform 'centos' 6 | 7 | context 'create a resolv config and verify config is created properly' do 8 | recipe do 9 | resolver_systemd_resolved_config '/etc/systemd/resolved.conf' do 10 | dns ['1.1.1.1', '1.0.0.1', '2606:4700:4700::1111', '2606:4700:4700::1001'] 11 | fallback_dns '8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844' 12 | domains 'localtest.com' 13 | end 14 | end 15 | 16 | it 'Creates the main configuration file' do 17 | is_expected.to render_file('/etc/systemd/resolved.conf') 18 | .with_content(/DNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001/) 19 | .with_content(/FallBackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844/) 20 | .with_content(/DNSSEC=allow-downgrade/) 21 | .with_content(/Domains=localtest.com/) 22 | .with_content(/CacheFromLocalhost=no/) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /templates/default/90-dns-none.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Generated by Chef Infra for <%= node['fqdn'] %> 3 | # Do NOT modify this file by hand, changes will be overwritten. 4 | # 5 | 6 | [main] 7 | dns=none 8 | -------------------------------------------------------------------------------- /templates/default/resolv.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Generated by Chef Infra for <%= node['fqdn'] %> 3 | # Do NOT modify this file by hand, changes will be overwritten. 4 | # 5 | 6 | <% unless nil_or_empty?(@domain) -%> 7 | domain <%= @domain %> 8 | <% end -%> 9 | <% unless nil_or_empty?(@search) -%> 10 | search <%= @search.join(' ') %> 11 | <% end -%> 12 | <% unless nil_or_empty?(@sortlist) -%> 13 | sortlist <%= @sortlist.join(' ') %> 14 | <% end -%> 15 | <% @nameservers.each do |nameserver| -%> 16 | nameserver <%= nameserver %> 17 | <% end %> 18 | <% unless nil_or_empty?(@options) -%> 19 | options<% @options.each do |option, value| -%> <%= option %><% unless nil_or_empty?(value) %>:<%= value %><% end %><% end -%> 20 | <% end -%> 21 | -------------------------------------------------------------------------------- /templates/default/resolved.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Generated by Chef Infra for <%= node['fqdn'] %> 3 | # Do NOT modify this file by hand, changes will be overwritten. 4 | # 5 | 6 | [Resolve] 7 | <% unless nil_or_empty?(@dns) -%> 8 | DNS=<%= @dns.join(' ') %> 9 | <% end -%> 10 | <% unless nil_or_empty?(@fallbackdns) -%> 11 | FallBackDNS=<%= @fallbackdns.join(' ') %> 12 | <% end -%> 13 | <% unless nil_or_empty?(@domains) -%> 14 | Domains=<%= @domains.join(' ') %> 15 | <% end -%> 16 | <% unless nil_or_empty?(@llmnr) -%> 17 | LLMNR=<%= systemd_value(@llmnr) %> 18 | <% end -%> 19 | <% unless nil_or_empty?(@multicastdns) -%> 20 | MulticastDNS=<%= systemd_value(@multicastdns) %> 21 | <% end -%> 22 | <% unless nil_or_empty?(@dnssec) -%> 23 | DNSSEC=<%= systemd_value(@dnssec )%> 24 | <% end -%> 25 | <% unless nil_or_empty?(@dnsovertls) -%> 26 | DNSOverTLS=<%= systemd_value(@dnsovertls) %> 27 | <% end -%> 28 | <% unless nil_or_empty?(@cache) -%> 29 | Cache=<%= systemd_value(@cache) %> 30 | <% end -%> 31 | <% unless nil_or_empty?(@cachefromlocalhost) -%> 32 | CacheFromLocalhost=<%= systemd_value(@cachefromlocalhost)%> 33 | <% end -%> 34 | <% unless nil_or_empty?(@dnsstublistener) -%> 35 | DNSStubListener=<%= systemd_value(@dnsstublistener) %> 36 | <% end -%> 37 | <% unless nil_or_empty?(@dnsstublistenerextra) -%> 38 | <% @dnsstublistenerextra.each do |dslx| -%> 39 | DNSStubListenerExtra=<%= dslx.strip %> 40 | <% end -%> 41 | <% end -%> 42 | <% unless nil_or_empty?(@readetchosts) -%> 43 | ReadEtcHosts=<%= systemd_value(@readetchosts) %> 44 | <% end -%> 45 | <% unless nil_or_empty?(@resolveunicastsinglelabel) -%> 46 | ResolveUnicastSingleLabel=<%= systemd_value(@resolveunicastsinglelabel) %> 47 | <% end -%> 48 | -------------------------------------------------------------------------------- /test/integration/cookbooks/resolver-test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'resolver-test' 2 | version '1.0.0' 3 | license 'Apache-2.0' 4 | depends 'resolver' 5 | -------------------------------------------------------------------------------- /test/integration/cookbooks/resolver-test/recipes/default.rb: -------------------------------------------------------------------------------- 1 | resolver_config '/etc/resolv.conf' do 2 | nameservers ['1.1.1.1', '1.0.0.1'] 3 | domain 'test.com' 4 | search ['test1.com', 'test2.com'] 5 | options( 6 | 'timeout' => 2, 7 | 'rotate' => nil, 8 | 'attempts' => 1 9 | ) 10 | override_system_configuration true 11 | atomic_update false 12 | end 13 | -------------------------------------------------------------------------------- /test/integration/cookbooks/resolver-test/recipes/systemd_resolved.rb: -------------------------------------------------------------------------------- 1 | resolver_systemd_resolved_config '/etc/systemd/resolved.conf' do 2 | dns ['1.1.1.1', '1.0.0.1', '2606:4700:4700::1111', '2606:4700:4700::1001'] 3 | fallback_dns '8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844' 4 | domains 'localtest.com' 5 | end 6 | 7 | service 'systemd-resolved' do 8 | action [:enable, :start] 9 | end 10 | -------------------------------------------------------------------------------- /test/integration/cookbooks/resolver-test/recipes/test_packages.rb: -------------------------------------------------------------------------------- 1 | dig_pkg = case node['platform_family'] 2 | when 'rhel', 'fedora', 'amazon', 'suse' 3 | 'bind-utils' 4 | when 'debian' 5 | 'dnsutils' 6 | when 'freebsd' 7 | 'bind-tools' 8 | end 9 | 10 | execute 'pkg update -f' do 11 | action :run 12 | end if platform_family?('freebsd') 13 | 14 | package dig_pkg unless dig_pkg.nil? 15 | -------------------------------------------------------------------------------- /test/integration/default/config_spec.rb: -------------------------------------------------------------------------------- 1 | describe file('/etc/resolv.conf') do 2 | it { should_not be_symlink } 3 | it { should be_file } 4 | its('content') { should match /nameserver 1.1.1.1/ } 5 | its('content') { should match /nameserver 1.0.0.1/ } 6 | its('content') { should match /domain test\.com/ } 7 | its('content') { should match /search test1\.com test2\.com/ } 8 | its('content') { should match /options timeout:2 rotate attempts:1/ } 9 | end 10 | 11 | describe command('curl https://www.google.com') do 12 | its('exit_status') { should eq 0 } 13 | end 14 | 15 | describe command('dig www.google.com') do 16 | its('stdout') { should match /SERVER: 1.1.1.1/ } 17 | end 18 | 19 | describe ini('/etc/NetworkManager/conf.d/90-dns-none.conf') do 20 | its('main.dns') { should eq 'none' } 21 | end if os.redhat? || os.name.eql?('fedora') 22 | -------------------------------------------------------------------------------- /test/integration/systemd_resolved/systemd_resolved_spec.rb: -------------------------------------------------------------------------------- 1 | describe file('/etc/systemd/resolved.conf') do 2 | its('content') { should match /DNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001/ } 3 | its('content') { should match /FallBackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844/ } 4 | its('content') { should match /DNSSEC=allow-downgrade/ } 5 | its('content') { should match /Domains=localtest.com/ } 6 | its('content') { should match /CacheFromLocalhost=no/ } 7 | end 8 | 9 | describe command('curl https://www.google.com') do 10 | its('exit_status') { should eq 0 } 11 | end 12 | 13 | describe command('dig www.google.com') do 14 | its('stdout') { should match /SERVER: 127.0.0.\d{1,3}/ } 15 | end 16 | 17 | describe service('systemd-resolved') do 18 | it { should be_installed } 19 | it { should be_enabled } 20 | it { should be_running } 21 | end 22 | --------------------------------------------------------------------------------