mirror of
https://github.com/inspec/inspec
synced 2025-02-16 22:18:38 +00:00
New postgres_hba_conf resource (#1964)
* Created pg_hba_conf resource Signed-off-by: Rony Xavier <rx294@nyu.edu> * Created pg_hba_conf resource Signed-off-by: Rony Xavier <rx294@nyu.edu> * Corrections * updated to parse auth-options Signed-off-by: Aaron Lippold <lippold@gmail.com> * updated `conf_path` instance var to `conf_file` for consistancy. Signed-off-by: Aaron Lippold <lippold@gmail.com> * pg_hba_conf - updated the parse_line method added test and doc files Signed-off-by: Rony Xavier <rx294@nyu.edu> * Updated few bugs on pg_hba_conf updated test files and docs Signed-off-by: Rony Xavier <rx294@nyu.edu> * Updated docs Signed-off-by: Rony Xavier <rx294@nyu.edu> * Made updates based on the reccomendations Signed-off-by: Rony Xavier <rx294@nyu.edu> * PR commit Signed-off-by: Rony Xavier <rx294@nyu.edu> * PR Commit Signed-off-by: Rony Xavier <rx294@nyu.edu> * Update Gemfile.lock * PR Commit Signed-off-by: Rony Xavier <rx294@nyu.edu> * Updated doc file for postgres_hba_conf resource to use 'cmp' matcher instead of 'eq' Signed-off-by: Rony Xavier <rx294@nyu.edu> * Made requested changes, except for SimpleConfig - will address that later. Signed-off-by: Aaron Lippold <lippold@gmail.com>
This commit is contained in:
parent
57864f1488
commit
224935e9cf
6 changed files with 265 additions and 0 deletions
104
docs/resources/postgres_hba_conf.md.erb
Normal file
104
docs/resources/postgres_hba_conf.md.erb
Normal file
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
title: About the postgres_hba_conf Resource
|
||||
---
|
||||
|
||||
# postgres_hba_conf
|
||||
|
||||
Use the `postgres_hba_conf` InSpec audit resource to test the client authentication data defined in the pg_hba.conf file.
|
||||
## Syntax
|
||||
|
||||
An `postgres_hba_conf` InSpec audit resource block declares client authentication data that should be tested:
|
||||
|
||||
describe postgres_hba_conf.where { type == 'local' } do
|
||||
its('auth_method') { should eq ['peer'] }
|
||||
end
|
||||
|
||||
where
|
||||
|
||||
* `'attribute'` is a attribute in the pg hba configuration file
|
||||
* `'filter_value'` is the value that is to be filtered for
|
||||
* `'value'` is the value that is to be matched expected
|
||||
|
||||
## Matchers
|
||||
|
||||
This InSpec audit resource matches any service that is listed in the HBA configuration file:
|
||||
|
||||
its('auth_method') { should_not cmp 'peer' }
|
||||
|
||||
or:
|
||||
|
||||
its('auth_method') { should cmp 'peer' }
|
||||
|
||||
For example:
|
||||
|
||||
describe postgres_hba_conf.where { type == 'type' } do
|
||||
its('auth_method') { should cmp 'value' }
|
||||
its('user') { should cmp 'value' }
|
||||
end
|
||||
|
||||
### be
|
||||
|
||||
<%= partial "/shared/matcher_be" %>
|
||||
|
||||
### cmp
|
||||
|
||||
<%= partial "/shared/matcher_cmp" %>
|
||||
|
||||
### eq
|
||||
|
||||
<%= partial "/shared/matcher_eq" %>
|
||||
|
||||
### include
|
||||
|
||||
<%= partial "/shared/matcher_include" %>
|
||||
|
||||
### match
|
||||
|
||||
<%= partial "/shared/matcher_match" %>
|
||||
|
||||
|
||||
## Supported Properties
|
||||
|
||||
'address', 'auth_method', 'auth_params', 'conf_dir' , 'conf_file' , 'database', 'params' ,'type', 'user'
|
||||
|
||||
## Property Examples and Return Types
|
||||
|
||||
### address([String])
|
||||
|
||||
`address` returns a an array of strings that matches the where condition of the filter table
|
||||
|
||||
describe postgres_hba_conf.where { type == 'local' } do
|
||||
its('address') { should cmp 'value' }
|
||||
end
|
||||
|
||||
### auth_method([String])
|
||||
|
||||
`auth_method` returns a an array of strings that matches the where condition of the filter table
|
||||
|
||||
describe postgres_hba_conf.where { type == 'local' } do
|
||||
its('auth_method') { should cmp 'value' }
|
||||
end
|
||||
|
||||
### database([String])
|
||||
|
||||
`database` returns a an array of strings that matches the where condition of the filter table
|
||||
|
||||
describe postgres_hba_conf.where { type == 'local' } do
|
||||
its('database') { should cmp 'value' }
|
||||
end
|
||||
|
||||
### type([String])
|
||||
|
||||
`type` returns a an array of strings that matches the where condition of the filter table
|
||||
|
||||
describe postgres_hba_conf.where { database == 'acme_test_db' } do
|
||||
its('type') { should cmp 'value' }
|
||||
end
|
||||
|
||||
### user([String])
|
||||
|
||||
`user` returns a an array of strings that matches the where condition of the filter table
|
||||
|
||||
describe postgres_hba_conf.where { database == 'acme_test_db' } do
|
||||
its('user') { should cmp 'value' }
|
||||
end
|
|
@ -122,6 +122,7 @@ require 'resources/package'
|
|||
require 'resources/packages'
|
||||
require 'resources/parse_config'
|
||||
require 'resources/passwd'
|
||||
require 'resources/postgres_hba_conf'
|
||||
require 'resources/postgres_ident_conf'
|
||||
require 'resources/pip'
|
||||
require 'resources/port'
|
||||
|
|
101
lib/resources/postgres_hba_conf.rb
Normal file
101
lib/resources/postgres_hba_conf.rb
Normal file
|
@ -0,0 +1,101 @@
|
|||
# encoding: utf-8
|
||||
# author: Rony Xavier,rx294@nyu.edu
|
||||
# author: Aaron Lippold, lippold@gmail.com
|
||||
|
||||
require 'resources/postgres'
|
||||
|
||||
module Inspec::Resources
|
||||
class PostgresHbaConf < Inspec.resource(1)
|
||||
name 'postgres_hba_conf'
|
||||
desc 'Use the `postgres_hba_conf` InSpec audit resource to test the client
|
||||
authentication data defined in the pg_hba.conf file.'
|
||||
example "
|
||||
describe postgres_hba_conf.where { type == 'local' } do
|
||||
its('auth_method') { should eq ['peer'] }
|
||||
end
|
||||
"
|
||||
|
||||
attr_reader :conf_file, :params
|
||||
|
||||
# @todo add checks to ensure that we have data in our file
|
||||
def initialize(hba_conf_path = nil)
|
||||
return skip_resource 'The `postgres_hba_conf` resource is not supported on your OS.' unless inspec.os.linux?
|
||||
@conf_file = hba_conf_path || File.expand_path('pg_hba.conf', inspec.postgres.conf_dir)
|
||||
@content = ''
|
||||
@params = {}
|
||||
read_content
|
||||
end
|
||||
|
||||
filter = FilterTable.create
|
||||
filter.add_accessor(:where)
|
||||
.add_accessor(:entries)
|
||||
.add(:type, field: 'type')
|
||||
.add(:database, field: 'database')
|
||||
.add(:user, field: 'user')
|
||||
.add(:address, field: 'address')
|
||||
.add(:auth_method, field: 'auth_method')
|
||||
.add(:auth_params, field: 'auth_params')
|
||||
|
||||
filter.connect(self, :params)
|
||||
|
||||
def to_s
|
||||
"Postgres Hba Config #{@conf_file}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clean_conf_file(conf_file = @conf_file)
|
||||
data = inspec.file(conf_file).content.to_s.lines
|
||||
content = []
|
||||
data.each do |line|
|
||||
line.chomp!
|
||||
content << line unless line.match(/^\s*#/) || line.empty?
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def read_content(config_file = @conf_file)
|
||||
file = inspec.file(config_file)
|
||||
|
||||
if !file.file?
|
||||
return skip_resource "Can't find file \"#{@conf_file}\""
|
||||
end
|
||||
|
||||
raw_conf = file.content
|
||||
|
||||
if raw_conf.empty? && !file.empty?
|
||||
return skip_resource("Can't read the contents of \"#{@conf_file}\"")
|
||||
end
|
||||
|
||||
# @todo use SimpleConfig here if we can
|
||||
# ^\s*(\S+)\s+(\S+)\s+(\S+)\s(?:(\d*.\d*.\d*.\d*\/\d*)|(::\/\d+))\s+(\S+)\s*(.*)?\s*$
|
||||
|
||||
@content = clean_conf_file(@conf_file)
|
||||
@params = parse_conf(@content)
|
||||
@params.each do |line|
|
||||
if line['type'] == 'local'
|
||||
line['auth_method'] = line['address']
|
||||
line['address'] = ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_conf(content)
|
||||
content.map do |line|
|
||||
parse_line(line)
|
||||
end.compact
|
||||
end
|
||||
|
||||
def parse_line(line)
|
||||
x = line.split(/\s+/)
|
||||
{
|
||||
'type' => x[0],
|
||||
'database' => x[1],
|
||||
'user' => x[2],
|
||||
'address' => x[3],
|
||||
'auth_method' => x[4],
|
||||
'auth_params' => ('' if x.length == 4) || x[5..-1].join(' '),
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -153,6 +153,7 @@ class MockLoader
|
|||
# Test DH parameters, 2048 bit long safe prime, generator 2 for dh_params in PEM format
|
||||
'dh_params.dh_pem' => mockfile.call('dh_params.dh_pem'),
|
||||
'default.toml' => mockfile.call('default.toml'),
|
||||
'/test/path/to/postgres/pg_hba.conf' => mockfile.call('pg_hba.conf'),
|
||||
'/etc/postgresql/9.5/main/pg_ident.conf' => mockfile.call('pg_ident.conf'),
|
||||
'C:/etc/postgresql/9.5/main/pg_ident.conf' => mockfile.call('pg_ident.conf'),
|
||||
'/etc/postgresql/9.5/main' => mockfile.call('9.5.main'),
|
||||
|
|
16
test/unit/mock/files/pg_hba.conf
Normal file
16
test/unit/mock/files/pg_hba.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
# BEGIN ANSIBLE MANAGED BLOCK
|
||||
# TYPE DATABASE USER ADDRESS METHOD
|
||||
local all all peer
|
||||
# host all all ::1/128 md5
|
||||
# host all all 127.0.0.1/32 md5
|
||||
host acme_test_db all ::1/0 md5
|
||||
host acme_test_db all 127.0.0.1/0 md5
|
||||
host acme_test all ::1/0 md5
|
||||
host acme_test all 127.0.0.1/0 md5
|
||||
# hostssl all all 127.0.0.1/32 cert clientcert=1 map=ssl-test
|
||||
# hostssl all all ::1/128 cert clientcert=1 map=ssl-test
|
||||
hostssl acme_test_db all ::/0 cert clientcert=1 map=ssl-test
|
||||
hostssl acme_test_db all 0.0.0.0/0 cert clientcert=1 map=ssl-test
|
||||
hostssl acme_test all ::/0 cert clientcert=1 map=ssl-test
|
||||
hostssl acme_test all 0.0.0.0/0 cert clientcert=1 map=ssl-test
|
||||
# END ANSIBLE MANAGED BLOCK
|
42
test/unit/resources/postgres_hba_conf_test.rb
Normal file
42
test/unit/resources/postgres_hba_conf_test.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
# encoding: utf-8
|
||||
# copyright: 2017
|
||||
# author: Aaron Lippold, lippold@gmail.com
|
||||
# author: Rony Xavier, rx294@nyu.edu
|
||||
|
||||
require 'helper'
|
||||
require 'inspec/resource'
|
||||
|
||||
describe 'Inspec::Resources::PGHbaConf' do
|
||||
describe 'PGHbaConf Paramaters' do
|
||||
resource = load_resource('postgres_hba_conf', '/test/path/to/postgres/pg_hba.conf')
|
||||
|
||||
it 'Verify postgres_hba_conf filtering by `type`' do
|
||||
entries = resource.where { type == 'local' }
|
||||
_(entries.database).must_include 'all'
|
||||
_(entries.auth_method).must_equal ['peer']
|
||||
end
|
||||
it 'Verify postgres_hba_conf filtering by `database`' do
|
||||
entries = resource.where { database == 'acme_test' }
|
||||
_(entries.type).must_include 'host'
|
||||
_(entries.user).must_include 'all'
|
||||
end
|
||||
it 'Verify postgres_hba_conf filtering by `auth_method`' do
|
||||
entries = resource.where { auth_method == 'cert' }
|
||||
_(entries.type).must_include 'hostssl'
|
||||
_(entries.database).must_include 'acme_test'
|
||||
end
|
||||
it 'Verify postgres_hba_conf attributes' do
|
||||
_(resource.auth_method).must_include 'cert'
|
||||
_(resource.database).must_include 'acme_test'
|
||||
_(resource.type).must_include 'hostssl'
|
||||
end
|
||||
it 'parses the pg_hba.conf file correctly' do
|
||||
_(resource.type).must_equal ["local", "host", "host", "host", "host", "hostssl", "hostssl", "hostssl", "hostssl"]
|
||||
_(resource.database).must_equal ["all", "acme_test_db", "acme_test_db", "acme_test", "acme_test", "acme_test_db", "acme_test_db", "acme_test", "acme_test"]
|
||||
_(resource.user).must_equal ["all", "all", "all", "all", "all", "all", "all", "all", "all"]
|
||||
_(resource.address).must_equal ["", "::1/0", "127.0.0.1/0", "::1/0", "127.0.0.1/0", "::/0", "0.0.0.0/0", "::/0", "0.0.0.0/0"]
|
||||
_(resource.auth_method).must_equal ["peer", "md5", "md5", "md5", "md5", "cert", "cert", "cert", "cert"]
|
||||
_(resource.auth_params).must_equal ["", "", "", "", "", "clientcert=1 map=ssl-test", "clientcert=1 map=ssl-test", "clientcert=1 map=ssl-test", "clientcert=1 map=ssl-test"]
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue