├── .github └── workflows │ ├── codespell.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .rubocop.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── controls └── postgres_spec.rb ├── inspec.yml └── renovate.json /.github/workflows/codespell.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Codespell - Spellcheck 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [master] 7 | pull_request: 8 | branches: [master] 9 | 10 | jobs: 11 | codespell: 12 | uses: "dev-sec/.github/.github/workflows/codespell.yml@main" 13 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: New release 3 | 4 | on: # yamllint disable-line rule:truthy 5 | workflow_dispatch: 6 | push: 7 | branches: 8 | - master 9 | 10 | jobs: 11 | generate_changelog: 12 | uses: dev-sec/.github/.github/workflows/baseline-release.yml@main 13 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | schedule: 9 | - cron: '0 6 * * *' 10 | 11 | jobs: 12 | test: 13 | uses: dev-sec/.github/.github/workflows/baseline-test.yml@main 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.librarian 2 | **/Puppetfile.lock 3 | **/.tmp 4 | Gemfile.lock 5 | Berksfile.lock 6 | inspec.lock 7 | nbproject 8 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | AllCops: 3 | Exclude: 4 | - vendor/**/* 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.1.1](https://github.com/dev-sec/postgres-baseline/tree/3.1.1) (2023-12-08) 4 | 5 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/3.1.0...3.1.1) 6 | 7 | **Implemented enhancements:** 8 | 9 | - Update Supported Versions [\#52](https://github.com/dev-sec/postgres-baseline/issues/52) 10 | - Switch back to simple InSpec service description [\#17](https://github.com/dev-sec/postgres-baseline/issues/17) 11 | - use centralised issue templates and workflows [\#48](https://github.com/dev-sec/postgres-baseline/pull/48) ([schurzi](https://github.com/schurzi)) 12 | 13 | **Merged pull requests:** 14 | 15 | - Remove control for running Database [\#54](https://github.com/dev-sec/postgres-baseline/pull/54) ([professormahi](https://github.com/professormahi)) 16 | - Fix \#52: Update supported versions [\#53](https://github.com/dev-sec/postgres-baseline/pull/53) ([professormahi](https://github.com/professormahi)) 17 | - ensure compatibility with new inspec version [\#51](https://github.com/dev-sec/postgres-baseline/pull/51) ([schurzi](https://github.com/schurzi)) 18 | - add spellchecking with codespell [\#50](https://github.com/dev-sec/postgres-baseline/pull/50) ([schurzi](https://github.com/schurzi)) 19 | - Configure Renovate [\#49](https://github.com/dev-sec/postgres-baseline/pull/49) ([renovate[bot]](https://github.com/apps/renovate)) 20 | - Change linting to Cookstyle [\#46](https://github.com/dev-sec/postgres-baseline/pull/46) ([schurzi](https://github.com/schurzi)) 21 | 22 | ## [3.1.0](https://github.com/dev-sec/postgres-baseline/tree/3.1.0) (2022-02-22) 23 | 24 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/3.0.1...3.1.0) 25 | 26 | **Implemented enhancements:** 27 | 28 | - Verify controls in running configuration [\#44](https://github.com/dev-sec/postgres-baseline/pull/44) ([FLiPp3r90](https://github.com/FLiPp3r90)) 29 | 30 | **Merged pull requests:** 31 | 32 | - Cookstyle Bot Auto Corrections with Cookstyle 7.14.0 [\#43](https://github.com/dev-sec/postgres-baseline/pull/43) ([cookstyle[bot]](https://github.com/apps/cookstyle)) 33 | 34 | ## [3.0.1](https://github.com/dev-sec/postgres-baseline/tree/3.0.1) (2022-01-12) 35 | 36 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/3.0.0...3.0.1) 37 | 38 | **Merged pull requests:** 39 | 40 | - use input instead of attribute [\#45](https://github.com/dev-sec/postgres-baseline/pull/45) ([micheelengronne](https://github.com/micheelengronne)) 41 | - fix rubocop error for Rakefile [\#42](https://github.com/dev-sec/postgres-baseline/pull/42) ([schurzi](https://github.com/schurzi)) 42 | - update release action [\#41](https://github.com/dev-sec/postgres-baseline/pull/41) ([schurzi](https://github.com/schurzi)) 43 | - add dependency to chef-config for CI [\#40](https://github.com/dev-sec/postgres-baseline/pull/40) ([schurzi](https://github.com/schurzi)) 44 | 45 | ## [3.0.0](https://github.com/dev-sec/postgres-baseline/tree/3.0.0) (2021-02-05) 46 | 47 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.7...3.0.0) 48 | 49 | **Breaking changes:** 50 | 51 | - Update PostgreSQL Baseline [\#39](https://github.com/dev-sec/postgres-baseline/pull/39) ([FLiPp3r90](https://github.com/FLiPp3r90)) 52 | 53 | **Merged pull requests:** 54 | 55 | - add github action for testing [\#38](https://github.com/dev-sec/postgres-baseline/pull/38) ([rndmh3ro](https://github.com/rndmh3ro)) 56 | 57 | ## [2.0.7](https://github.com/dev-sec/postgres-baseline/tree/2.0.7) (2020-07-23) 58 | 59 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.6...2.0.7) 60 | 61 | **Merged pull requests:** 62 | 63 | - The release draft references the correct SHA [\#36](https://github.com/dev-sec/postgres-baseline/pull/36) ([micheelengronne](https://github.com/micheelengronne)) 64 | 65 | ## [2.0.6](https://github.com/dev-sec/postgres-baseline/tree/2.0.6) (2020-06-18) 66 | 67 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.5...2.0.6) 68 | 69 | **Merged pull requests:** 70 | 71 | - version alignment [\#35](https://github.com/dev-sec/postgres-baseline/pull/35) ([micheelengronne](https://github.com/micheelengronne)) 72 | 73 | ## [2.0.5](https://github.com/dev-sec/postgres-baseline/tree/2.0.5) (2020-06-18) 74 | 75 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.4...2.0.5) 76 | 77 | **Closed issues:** 78 | 79 | - Support sha256 on Postgresql 10+ [\#24](https://github.com/dev-sec/postgres-baseline/issues/24) 80 | 81 | **Merged pull requests:** 82 | 83 | - github actions release [\#34](https://github.com/dev-sec/postgres-baseline/pull/34) ([micheelengronne](https://github.com/micheelengronne)) 84 | - Use entries instead of list. [\#33](https://github.com/dev-sec/postgres-baseline/pull/33) ([ojongerius](https://github.com/ojongerius)) 85 | - scram sha 256 [\#31](https://github.com/dev-sec/postgres-baseline/pull/31) ([chris-rock](https://github.com/chris-rock)) 86 | - Support SCRAM-SHA-256 password hashing on 10+ [\#30](https://github.com/dev-sec/postgres-baseline/pull/30) ([kravietz](https://github.com/kravietz)) 87 | 88 | ## [2.0.4](https://github.com/dev-sec/postgres-baseline/tree/2.0.4) (2019-05-15) 89 | 90 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.3...2.0.4) 91 | 92 | **Closed issues:** 93 | 94 | - Update supported versions [\#23](https://github.com/dev-sec/postgres-baseline/issues/23) 95 | 96 | **Merged pull requests:** 97 | 98 | - Bump version to 2.0.4 and switch to inspec 3 for check [\#32](https://github.com/dev-sec/postgres-baseline/pull/32) ([alexpop](https://github.com/alexpop)) 99 | - Update issue templates [\#29](https://github.com/dev-sec/postgres-baseline/pull/29) ([rndmh3ro](https://github.com/rndmh3ro)) 100 | - update rubocop dependency [\#28](https://github.com/dev-sec/postgres-baseline/pull/28) ([chris-rock](https://github.com/chris-rock)) 101 | - Update baseline title [\#27](https://github.com/dev-sec/postgres-baseline/pull/27) ([chris-rock](https://github.com/chris-rock)) 102 | - allows patch levels \(ie 9.5.14\) [\#26](https://github.com/dev-sec/postgres-baseline/pull/26) ([ojongerius](https://github.com/ojongerius)) 103 | - Fix \#23 - update supported versions [\#25](https://github.com/dev-sec/postgres-baseline/pull/25) ([pmav99](https://github.com/pmav99)) 104 | 105 | ## [2.0.3](https://github.com/dev-sec/postgres-baseline/tree/2.0.3) (2017-12-01) 106 | 107 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.2...2.0.3) 108 | 109 | **Merged pull requests:** 110 | 111 | - make sure attributes are strings [\#22](https://github.com/dev-sec/postgres-baseline/pull/22) ([arlimus](https://github.com/arlimus)) 112 | 113 | ## [2.0.2](https://github.com/dev-sec/postgres-baseline/tree/2.0.2) (2017-06-27) 114 | 115 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.1...2.0.2) 116 | 117 | **Merged pull requests:** 118 | 119 | - inspec check fix [\#21](https://github.com/dev-sec/postgres-baseline/pull/21) ([chris-rock](https://github.com/chris-rock)) 120 | 121 | ## [2.0.1](https://github.com/dev-sec/postgres-baseline/tree/2.0.1) (2017-05-08) 122 | 123 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/2.0.0...2.0.1) 124 | 125 | **Merged pull requests:** 126 | 127 | - update metadata [\#19](https://github.com/dev-sec/postgres-baseline/pull/19) ([chris-rock](https://github.com/chris-rock)) 128 | - restrict ruby testing to version 2.3.3 and update gemfile [\#18](https://github.com/dev-sec/postgres-baseline/pull/18) ([atomic111](https://github.com/atomic111)) 129 | - adjust the service for each os type and correct the control 10 [\#16](https://github.com/dev-sec/postgres-baseline/pull/16) ([atomic111](https://github.com/atomic111)) 130 | - remove the sudo command and remove duplicate control [\#15](https://github.com/dev-sec/postgres-baseline/pull/15) ([atomic111](https://github.com/atomic111)) 131 | 132 | ## [2.0.0](https://github.com/dev-sec/postgres-baseline/tree/2.0.0) (2017-01-05) 133 | 134 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/1.1.0...2.0.0) 135 | 136 | **Merged pull requests:** 137 | 138 | - 2.0.0 [\#14](https://github.com/dev-sec/postgres-baseline/pull/14) ([chris-rock](https://github.com/chris-rock)) 139 | - Migrate to InSpec [\#13](https://github.com/dev-sec/postgres-baseline/pull/13) ([atomic111](https://github.com/atomic111)) 140 | 141 | ## [1.1.0](https://github.com/dev-sec/postgres-baseline/tree/1.1.0) (2015-10-15) 142 | 143 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/1.0.0...1.1.0) 144 | 145 | **Merged pull requests:** 146 | 147 | - install server and apply hardening in separate steps [\#5](https://github.com/dev-sec/postgres-baseline/pull/5) ([chris-rock](https://github.com/chris-rock)) 148 | - bugfix: lint error [\#4](https://github.com/dev-sec/postgres-baseline/pull/4) ([chris-rock](https://github.com/chris-rock)) 149 | - add ssl test back in for 'off' setting [\#3](https://github.com/dev-sec/postgres-baseline/pull/3) ([ehaselwanter](https://github.com/ehaselwanter)) 150 | 151 | ## [1.0.0](https://github.com/dev-sec/postgres-baseline/tree/1.0.0) (2014-08-13) 152 | 153 | [Full Changelog](https://github.com/dev-sec/postgres-baseline/compare/3bad2740268b24fc8af9df23f1f2bdebce3ecce2...1.0.0) 154 | 155 | **Merged pull requests:** 156 | 157 | - version 0.9 of tests, disabled ssl check for now as it requires more work on chef and puppet with redhat derivates [\#2](https://github.com/dev-sec/postgres-baseline/pull/2) ([ehaselwanter](https://github.com/ehaselwanter)) 158 | - first pass of postgres hardening requirement tests [\#1](https://github.com/dev-sec/postgres-baseline/pull/1) ([ehaselwanter](https://github.com/ehaselwanter)) 159 | 160 | 161 | 162 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 163 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gem 'cookstyle' 6 | gem 'highline' 7 | gem 'rack' 8 | gem 'rake' 9 | gem 'rubocop' 10 | 11 | group :tools do 12 | gem 'github_changelog_generator' 13 | gem 'pry-coolline' 14 | end 15 | 16 | source 'https://packagecloud.io/cinc-project/stable' do 17 | gem 'chef-config' 18 | gem 'cinc-auditor-bin' 19 | end 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DevSec PostgreSQL Baseline 2 | 3 | This Compliance Profile ensures, that all hardening projects keep the same quality. 4 | 5 | - https://github.com/dev-sec/chef-postgres-hardening 6 | - https://github.com/dev-sec/puppet-postgres-hardening 7 | 8 | ## Standalone Usage 9 | 10 | This Compliance Profile requires [InSpec](https://github.com/chef/inspec) for execution: 11 | 12 | ``` 13 | $ git clone https://github.com/dev-sec/postgres-baseline 14 | $ inspec exec postgres-baseline 15 | ``` 16 | 17 | You can also execute the profile directly from Github: 18 | 19 | ``` 20 | $ inspec exec https://github.com/dev-sec/postgres-baseline 21 | ``` 22 | 23 | ## License and Author 24 | 25 | - Author:: Patrick Muench 26 | - Author:: Dominik Richter 27 | - Author:: Christoph Hartmann 28 | - Author:: Edmund Haselwanter 29 | 30 | - Copyright 2014-2022, The DevSec Hardening Framework Team 31 | 32 | Licensed under the Apache License, Version 2.0 (the "License"); 33 | you may not use this file except in compliance with the License. 34 | You may obtain a copy of the License at 35 | 36 | http://www.apache.org/licenses/LICENSE-2.0 37 | 38 | Unless required by applicable law or agreed to in writing, software 39 | distributed under the License is distributed on an "AS IS" BASIS, 40 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 41 | See the License for the specific language governing permissions and 42 | limitations under the License. 43 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'cookstyle' 4 | require 'rake/testtask' 5 | require 'rubocop/rake_task' 6 | 7 | # Rubocop 8 | desc 'Run Rubocop lint checks' 9 | task :rubocop do 10 | RuboCop::RakeTask.new 11 | end 12 | 13 | RuboCop::RakeTask.new(:cookstyle) do |task| 14 | task.options << '--display-cop-names' 15 | end 16 | 17 | # lint the project 18 | desc 'Run robocop linter' 19 | task lint: [:rubocop] 20 | 21 | # run tests 22 | task default: [:lint, 'test:check'] 23 | 24 | namespace :test do 25 | # run inspec check to verify that the profile is properly configured 26 | task :check do 27 | require 'inspec' 28 | puts " * Checking profile with InSpec version: #{Inspec::VERSION}" 29 | profile = Inspec::Profile.for_target('.', backend: Inspec::Backend.create(Inspec::Config.mock)) 30 | pp profile.check 31 | end 32 | end 33 | 34 | task :changelog do 35 | # Automatically generate a changelog for this project. Only loaded if 36 | # the necessary gem is installed. By default its picking up the version from 37 | # inspec.yml. You can override that behavior with `rake changelog to=1.2.0` 38 | 39 | require 'yaml' 40 | metadata = YAML.load_file('inspec.yml') 41 | v = ENV['to'] || metadata['version'] 42 | puts " * Generating changelog for version #{v}" 43 | require 'github_changelog_generator/task' 44 | GitHubChangelogGenerator::RakeTask.new :changelog do |config| 45 | config.future_release = v 46 | config.user = 'dev-sec' 47 | config.project = 'postgres-baseline' 48 | end 49 | Rake::Task[:changelog].execute 50 | rescue LoadError 51 | puts '>>>>> GitHub Changelog Generator not loaded, omitting tasks' 52 | end 53 | -------------------------------------------------------------------------------- /controls/postgres_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Copyright:: 2016, Patrick Muench 4 | # Copyright:: 2016-2019 DevSec Hardening Framework Team 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # author: Christoph Hartmann 19 | # author: Dominik Richter 20 | # author: Patrick Muench 21 | 22 | title 'PostgreSQL Server Configuration' 23 | 24 | # inputs 25 | USER = input('user', value: 'postgres') 26 | PASSWORD = input('password', value: 'iloverandompasswordsbutthiswilldo') 27 | POSTGRES_DATA = input('postgres_data', value: postgres.data_dir) 28 | POSTGRES_CONF_DIR = input('postgres_conf_dir', value: postgres.conf_dir) 29 | POSTGRES_CONF_PATH = input('postgres_conf_path', value: File.join(POSTGRES_CONF_DIR.to_s, 'postgresql.conf')) 30 | POSTGRES_HBA_CONF_FILE = input('postgres_hba_conf_file', value: File.join(POSTGRES_CONF_DIR.to_s, 'pg_hba.conf')) 31 | POSTGRES_LOG_DIR = input('postgres_log_dir', value: '/var/log/postgresql') 32 | 33 | only_if do 34 | command('psql').exist? 35 | end 36 | 37 | control 'postgres-02' do 38 | impact 1.0 39 | title 'Use stable postgresql version' 40 | desc 'Use only community or commercially supported version of the PostgreSQL software (https://www.postgresql.org/support/versioning/). Do not use RC, DEVEL or BETA versions in a production environment.' 41 | describe command('psql -V') do 42 | its('stdout') { should match /^psql\s\(PostgreSQL\)\s(13|14|15|16|17).*/ } 43 | end 44 | describe command('psql -V') do 45 | its('stdout') { should_not match /RC/ } 46 | its('stdout') { should_not match /DEVEL/ } 47 | its('stdout') { should_not match /BETA/ } 48 | end 49 | end 50 | 51 | control 'postgres-03' do 52 | impact 1.0 53 | title 'Run one postgresql instance per operating system' 54 | desc 'Only one postgresql database instance must be running on an operating system instance (both physical HW or virtualized).' 55 | case os[:name] 56 | when 'redhat', 'centos', 'oracle', 'fedora' 57 | describe processes('bin/postmaster') do 58 | its('entries.length') { should eq 1 } 59 | end 60 | when 'debian', 'ubuntu' 61 | describe processes('bin/postgres') do 62 | its('entries.length') { should eq 1 } 63 | end 64 | end 65 | end 66 | 67 | control 'postgres-04' do 68 | impact 1.0 69 | title 'Only "c" and "internal" should be used as non-trusted procedural languages' 70 | desc 'If additional programming languages (e.g. plperl) are installed with non-trust mode, then it is possible to gain OS-level access permissions.' 71 | describe postgres_session(USER, PASSWORD).query('SELECT count (*) FROM pg_language WHERE lanpltrusted = \'f\' AND lanname!=\'internal\' AND lanname!=\'c\';') do 72 | its('output') { should eq '0' } 73 | end 74 | end 75 | 76 | control 'postgres-05' do 77 | impact 1.0 78 | title 'Delete not required procedural languages' 79 | desc 'You should delete programming languages which are not necessary. "internal", "c", "plpgsql" and "sql" are allowed defaults.' 80 | describe postgres_session(USER, PASSWORD).query("SELECT COUNT(*) FROM pg_language where lanname NOT IN ('internal', 'c', 'sql', 'plpgsql');") do 81 | its('output') { should eq '0' } 82 | end 83 | end 84 | 85 | control 'postgres-06' do 86 | impact 1.0 87 | title 'Set a password for each user' 88 | desc 'It tests for usernames which does not set a password.' 89 | describe postgres_session(USER, PASSWORD).query('SELECT count(*) FROM pg_shadow WHERE passwd IS NULL;') do 90 | its('output') { should eq '0' } 91 | end 92 | end 93 | 94 | control 'postgres-07' do 95 | impact 1.0 96 | title 'Use salted hash to store postgresql passwords' 97 | desc 'Store postgresql passwords in salted hash format (e.g. salted MD5).' 98 | case postgres.version 99 | when /^9/ 100 | describe postgres_session(USER, PASSWORD).query('SELECT passwd FROM pg_shadow;') do 101 | its('output') { should match /^md5\S*$/i } 102 | end 103 | describe postgres_session(USER, PASSWORD).query('SHOW password_encryption;') do 104 | its('output') { should eq 'on' } 105 | end 106 | else 107 | describe postgres_session(USER, PASSWORD).query('SELECT passwd FROM pg_shadow;') do 108 | its('output') { should match /^scram-sha-256\S*$/i } 109 | end 110 | describe postgres_session(USER, PASSWORD).query('SHOW password_encryption;') do 111 | its('output') { should eq 'scram-sha-256' } 112 | end 113 | end 114 | end 115 | 116 | control 'postgres-08' do 117 | impact 1.0 118 | title 'Only the postgresql database administrator should have SUPERUSER, CREATEDB or CREATEROLE privileges.' 119 | desc 'Granting extensive privileges to ordinary users can cause various security problems, such as: intentional/ unintentional access, modification or destroying data' 120 | describe postgres_session(USER, PASSWORD).query('SELECT count(*) FROM pg_roles WHERE rolsuper IS TRUE OR rolcreaterole IS TRUE or rolcreatedb IS TRUE;') do 121 | its('output') { should eq '1' } 122 | end 123 | end 124 | 125 | control 'postgres-09' do 126 | impact 1.0 127 | title 'Only the DBA should have privileges on pg_catalog.pg_authid table.' 128 | desc 'In pg_catalog.pg_authid table there are stored credentials such as username and password. If hacker has access to the table, then he can extract these credentials.' 129 | describe postgres_session(USER, PASSWORD).query("SELECT grantee FROM information_schema.role_table_grants WHERE table_name='pg_authid' group by grantee;") do 130 | its('output') { should eq 'postgres' } 131 | end 132 | end 133 | 134 | control 'postgres-10' do 135 | impact 1.0 136 | title 'The PostgreSQL config directory and file should be assigned exclusively to the database account (such as "postgres").' 137 | desc 'If file permissions on config files are not property defined, other users may read, modify or delete those files.' 138 | describe file(POSTGRES_CONF_DIR) do 139 | it { should be_directory } 140 | it { should be_owned_by USER } 141 | it { should be_readable.by('owner') } 142 | it { should_not be_readable.by('group') } 143 | it { should_not be_readable.by('other') } 144 | it { should be_writable.by('owner') } 145 | it { should_not be_writable.by('group') } 146 | it { should_not be_writable.by('other') } 147 | it { should be_executable.by('owner') } 148 | it { should_not be_executable.by('group') } 149 | it { should_not be_executable.by('other') } 150 | end 151 | describe file(POSTGRES_CONF_PATH) do 152 | it { should be_file } 153 | it { should be_owned_by USER } 154 | it { should be_readable.by('owner') } 155 | it { should be_readable.by('group') } 156 | it { should_not be_readable.by('other') } 157 | it { should be_writable.by('owner') } 158 | it { should_not be_writable.by('group') } 159 | it { should_not be_writable.by('other') } 160 | it { should_not be_executable.by('owner') } 161 | it { should_not be_executable.by('group') } 162 | it { should_not be_executable.by('other') } 163 | end 164 | describe file(POSTGRES_HBA_CONF_FILE) do 165 | it { should be_file } 166 | it { should be_owned_by USER } 167 | it { should be_readable.by('owner') } 168 | it { should_not be_readable.by('group') } 169 | it { should_not be_readable.by('other') } 170 | it { should be_writable.by('owner') } 171 | it { should_not be_writable.by('group') } 172 | it { should_not be_writable.by('other') } 173 | it { should_not be_executable.by('owner') } 174 | it { should_not be_executable.by('group') } 175 | it { should_not be_executable.by('other') } 176 | end 177 | end 178 | 179 | control 'postgres-11' do 180 | impact 1.0 181 | title 'It is recommended to activate ssl communication.' 182 | desc 'The hardening-cookbook will delete the links from #var/lib/postgresql/%postgresql-version%/main/server.crt to etc/ssl/certs/ssl-cert-snakeoil.pem and #var/lib/postgresql/%postgresql-version%/main/server.key to etc/ssl/private/ssl-cert-snakeoil.key on Debian systems. This certificates are self-signed (see http://en.wikipedia.org/wiki/Snake_oil_%28cryptography%29) and therefore not trusted. You have to #provide our own trusted certificates for SSL.' 183 | describe postgres_session(USER, PASSWORD).query('SHOW ssl;') do 184 | its('output') { should eq 'on' } 185 | end 186 | end 187 | 188 | control 'postgres-12' do 189 | impact 1.0 190 | title 'Use strong chiphers for ssl communication' 191 | desc 'The following categories of SSL Ciphers must not be used: ADH, LOW, EXP and MD5. A very good description for secure postgres installation / configuration can be found at: https://bettercrypto.org' 192 | describe postgres_session(USER, PASSWORD).query('SHOW ssl_ciphers;') do 193 | its('output') { should eq 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' } 194 | end 195 | end 196 | 197 | control 'postgres-13' do 198 | impact 1.0 199 | title 'Require peer auth_method for local users' 200 | desc 'Require peer auth_method for local users.' 201 | describe postgres_hba_conf(POSTGRES_HBA_CONF_FILE).where { type == 'local' } do 202 | its('auth_method') { should all eq 'peer' } 203 | end 204 | end 205 | 206 | control 'postgres-14' do 207 | impact 1.0 208 | title 'Require only trusted authentication methods in pg_hba.conf' 209 | desc 'Require trusted auth method for ALL users, peers in pg_hba.conf and do not allow untrusted authentication methods.' 210 | case postgres.version 211 | when /^9/ 212 | describe postgres_hba_conf(POSTGRES_HBA_CONF_FILE).where { type == 'hostssl' } do 213 | its('auth_method') { should all eq 'md5' } 214 | end 215 | else 216 | describe postgres_hba_conf(POSTGRES_HBA_CONF_FILE).where { type == 'hostssl' } do 217 | its('auth_method') { should all eq 'scram-sha-256' } 218 | end 219 | end 220 | end 221 | 222 | control 'postgres-15' do 223 | impact 1.0 224 | title 'Require SSL communication between all peers' 225 | desc 'Do not allow communication without SSL among all peers.' 226 | describe file(POSTGRES_HBA_CONF_FILE) do 227 | its('content') { should_not match /^host .*/ } 228 | its('content') { should_not match /^hostnossl .*/ } 229 | end 230 | end 231 | 232 | control 'postgres-16' do 233 | impact 1.0 234 | title 'Enable logging functions' 235 | desc 'Logging functions must be turned on and properly configured according / compliant to local law.' 236 | describe postgres_session(USER, PASSWORD).query('SHOW logging_collector;') do 237 | its('output') { should eq 'on' } 238 | end 239 | describe postgres_session(USER, PASSWORD).query('SHOW log_connections;') do 240 | its('output') { should eq 'on' } 241 | end 242 | describe postgres_session(USER, PASSWORD).query('SHOW log_disconnections;') do 243 | its('output') { should eq 'on' } 244 | end 245 | describe postgres_session(USER, PASSWORD).query('SHOW log_duration;') do 246 | its('output') { should eq 'on' } 247 | end 248 | describe postgres_session(USER, PASSWORD).query('SHOW log_hostname;') do 249 | its('output') { should eq 'on' } 250 | end 251 | describe postgres_session(USER, PASSWORD).query('SHOW log_directory;') do 252 | its('output') { should_not eq 'log' } 253 | end 254 | describe postgres_session(USER, PASSWORD).query('SHOW log_line_prefix;') do 255 | its('output') { should eq '%t %u %d %h' } 256 | end 257 | end 258 | 259 | control 'postgres-17' do 260 | impact 1.0 261 | title 'Grants should not be assigned to public' 262 | desc 'Grants should not be assigned to public to avoid issues with tenant separations.' 263 | describe postgres_session(USER, PASSWORD).query("SELECT COUNT(*) FROM information_schema.table_privileges WHERE grantee = 'PUBLIC' AND table_schema NOT LIKE 'pg_catalog' AND table_schema NOT LIKE 'information_schema';") do 264 | its('output') { should eq '0' } 265 | end 266 | end 267 | 268 | control 'postgres-18' do 269 | impact 1.0 270 | title 'Grants should not be assigned with grant option privilege' 271 | desc 'Grants should not be assigned with grant option except postgresql admin superuser.' 272 | describe postgres_session(USER, PASSWORD).query("SELECT COUNT(is_grantable) FROM information_schema.table_privileges WHERE grantee NOT LIKE 'postgres' AND is_grantable = 'YES';") do 273 | its('output') { should eq '0' } 274 | end 275 | end 276 | 277 | control 'postgres-19' do 278 | impact 1.0 279 | title 'Restrictive usage of SQL functions with security definer' 280 | desc 'Avoid SQL functions with security definer.' 281 | describe postgres_session(USER, PASSWORD).query("SELECT COUNT(*) FROM pg_proc JOIN pg_namespace ON pg_proc.pronamespace=pg_namespace.oid JOIN pg_user ON pg_proc.proowner=pg_user.usesysid WHERE prosecdef='t';") do 282 | its('output') { should eq '0' } 283 | end 284 | end 285 | 286 | control 'postgres-20' do 287 | impact 1.0 288 | title 'The PostgreSQL data and log directory should be assigned exclusively to the database account (such as "postgres").' 289 | desc 'The PostgreSQL data and log directory should be assigned exclusively to the database account (such as "postgres").' 290 | describe file(POSTGRES_DATA) do 291 | it { should be_directory } 292 | it { should be_owned_by USER } 293 | it { should be_readable.by('owner') } 294 | it { should_not be_readable.by('group') } 295 | it { should_not be_readable.by('other') } 296 | it { should be_writable.by('owner') } 297 | it { should_not be_writable.by('group') } 298 | it { should_not be_writable.by('other') } 299 | it { should be_executable.by('owner') } 300 | it { should_not be_executable.by('group') } 301 | it { should_not be_executable.by('other') } 302 | end 303 | describe file(POSTGRES_LOG_DIR) do 304 | it { should be_directory } 305 | it { should be_owned_by USER } 306 | it { should be_readable.by('owner') } 307 | it { should_not be_readable.by('group') } 308 | it { should_not be_readable.by('other') } 309 | it { should be_writable.by('owner') } 310 | it { should_not be_writable.by('group') } 311 | it { should_not be_writable.by('other') } 312 | it { should be_executable.by('owner') } 313 | it { should_not be_executable.by('group') } 314 | it { should_not be_executable.by('other') } 315 | end 316 | end 317 | -------------------------------------------------------------------------------- /inspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: postgres-baseline 3 | title: DevSec PostgreSQL Baseline 4 | maintainer: DevSec Hardening Framework Team 5 | copyright: DevSec Hardening Framework Team 6 | copyright_email: hello@dev-sec.io 7 | license: Apache-2.0 8 | summary: Test-suite for best-practice postgres hardening 9 | inspec_version: '>= 4.6.3' 10 | version: 3.1.1 11 | supports: 12 | - os-family: unix 13 | inputs: 14 | - name: user 15 | description: define the postgresql user to access the database 16 | - name: password 17 | description: define the postgresql password to access the database 18 | - name: postgres_data 19 | description: define the postgresql data directory 20 | - name: postgres_conf_dir 21 | description: define the postgresql configuration directory 22 | - name: postgres_conf_path 23 | description: define path for the postgresql configuration file 24 | - name: postgres_hba_conf_file 25 | description: define path for the postgresql configuration file 26 | - name: postgres_log_dir 27 | description: define path for the postgresql log file 28 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base", 5 | ":gitSignOff" 6 | ], 7 | "dependencyDashboard": true, 8 | "dependencyDashboardAutoclose": true, 9 | "packageRules": [ 10 | { 11 | "matchUpdateTypes": ["patch", "minor"], 12 | "automerge": true 13 | } 14 | ] 15 | } 16 | --------------------------------------------------------------------------------