Skip to content

Commit 69058e7

Browse files
allow more mappings per mapname (#786)
feat: Support multiple mappings per map name in pg_ident.conf - Make entries unique based on map_name + system_username + database_username combination, allowing multiple system users to share the same map name - Fix spacing issues with long map names that previously caused invalid formatting - Resolve markdown linting errors with non-clickable URLs Refs: - https://www.postgresql.org/docs/current/auth-username-maps.html - #733 --------- Co-authored-by: Dan Webb <[email protected]>
1 parent 31ef26b commit 69058e7

File tree

6 files changed

+83
-48
lines changed

6 files changed

+83
-48
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ This file is used to list changes made in the last 3 major versions of the postg
44

55
## Unreleased
66

7-
Standardise files with files in sous-chefs/repo-management
7+
- Fix where only a single mapname was being set in the `pg_hba.conf` file when multiple were specified
8+
- Standardise files with files in sous-chefs/repo-management
89

910
## 12.1.0 - *2025-05-17*
1011

documentation/postgresql_install.md

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,32 @@
1717

1818
## Properties
1919

20-
| Name | Name? | Type | Default | Description | Allowed Values |
21-
| ---------------------------------- | ----- | --------------- | ----------------- | ------------------------------------------------ | -------------- |
22-
| `sensitive` | | true, false | `true` | | |
23-
| `version` | | String, Integer | `'17'` | Version to install | |
24-
| `source` | | String, Symbol | `:repo` | Installation source | repo, os |
25-
| `client_packages` | | String, Array | platform specific | Client packages to install | |
26-
| `server_packages` | | String, Array | platform specific | Server packages to install | |
27-
| `repo_pgdg` | | true, false | `true` | Create pgdg repo | |
28-
| `setup_repo_pgdg` | | true, false | value of previous | Whether or not to manage the pgdg repo | |
29-
| `repo_pgdg_common` | | true, false | `true` | Create pgdg-common repo | |
30-
| `setup_repo_pgdg_common` | | true, false | value of previous | Whether or not to manage the pgdg_common repo | |
31-
| `repo_pgdg_source` | | true, false | `false` | Create pgdg-source repo | |
32-
| `setup_repo_pgdg_source` | | true, false | value of previous | Whether or not to manage the pgdg_source repo | |
33-
| `repo_pgdg_updates_testing` | | true, false | `false` | Create pgdg-updates-testing repo | |
34-
| `setup_repo_pgdg_updates_testing` | | true, false | value of previous | Whether or not to manage the pgdg_updates_testing repo | |
35-
| `repo_pgdg_source_updates_testing` | | true, false | `false` | Create pgdg-source-updates-testing repo | |
36-
| `setup_repo_pgdg_source_updates_testing` | | true, false | value of previous | Whether or not to manage the pgdg_source_updates_testing repo | |
37-
| `yum_gpg_key_uri` | | String | platform specific | YUM/DNF GPG key URL | |
38-
| `apt_repository_uri` | | String | [https://download.postgresql.org/pub/repos/apt/](https://download.postgresql.org/pub/repos/apt/) | apt repository URL | |
39-
| `apt_gpg_key_uri` | | String | [https://download.postgresql.org/pub/repos/apt/ACCC4CF8.asc](https://download.postgresql.org/pub/repos/apt/ACCC4CF8.asc) | apt GPG key URL | |
40-
| `initdb_additional_options` | | String | | Additional options to pass to the initdb command | |
41-
| `initdb_locale` | | String | | Locale to use for the initdb command | |
42-
| `initdb_encoding` | | String | | Encoding to use for the initdb command | |
43-
| `initdb_user` | | String | `'postgres'` | User to run the initdb command as | |
20+
<!-- markdownlint-disable MD034 -->
21+
| Name | Name? | Type | Default | Description | Allowed Values |
22+
| ---------------------------------------- | ----- | --------------- | ----------------- | ------------------------------------------------ | -------------- |
23+
| `sensitive` | | true, false | `true` | | |
24+
| `version` | | String, Integer | `'17'` | Version to install | |
25+
| `source` | | String, Symbol | `:repo` | Installation source | repo, os |
26+
| `client_packages` | | String, Array | platform specific | Client packages to install | |
27+
| `server_packages` | | String, Array | platform specific | Server packages to install | |
28+
| `repo_pgdg` | | true, false | `true` | Create pgdg repo | |
29+
| `setup_repo_pgdg` | | true, false | value of previous | Whether or not to manage the pgdg repo | |
30+
| `repo_pgdg_common` | | true, false | `true` | Create pgdg-common repo | |
31+
| `setup_repo_pgdg_common` | | true, false | value of previous | Whether or not to manage the pgdg_common repo | |
32+
| `repo_pgdg_source` | | true, false | `false` | Create pgdg-source repo | |
33+
| `setup_repo_pgdg_source` | | true, false | value of previous | Whether or not to manage the pgdg_source repo | |
34+
| `repo_pgdg_updates_testing` | | true, false | `false` | Create pgdg-updates-testing repo | |
35+
| `setup_repo_pgdg_updates_testing` | | true, false | value of previous | Whether or not to manage the pgdg_updates_testing repo | |
36+
| `repo_pgdg_source_updates_testing` | | true, false | `false` | Create pgdg-source-updates-testing repo | |
37+
| `setup_repo_pgdg_source_updates_testing` | | true, false | value of previous | Whether or not to manage the pgdg_source_updates_testing repo | |
38+
| `yum_gpg_key_uri` | | String | platform specific | YUM/DNF GPG key URL | |
39+
| `apt_repository_uri` | | String | https://download.postgresql.org/pub/repos/apt/ | apt repository URL | |
40+
| `apt_gpg_key_uri` | | String | https://download.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt GPG key URL | |
41+
| `initdb_additional_options` | | String | | Additional options to pass to the initdb command | |
42+
| `initdb_locale` | | String | | Locale to use for the initdb command | |
43+
| `initdb_encoding` | | String | | Encoding to use for the initdb command | |
44+
| `initdb_user` | | String | `'postgres'` | User to run the initdb command as | |
45+
<!-- markdownlint-enable MD034 -->
4446

4547
## Libraries
4648

libraries/ident.rb

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ def initialize
7979
def add(entry)
8080
raise unless entry.is_a?(PgIdentFileEntry)
8181

82-
return false if entry?(entry.map_name)
82+
return false if entry?(entry.map_name, entry.system_username, entry.database_username)
8383

8484
@entries.push(entry)
8585

8686
sort!
8787
end
8888

89-
def entry(map_name)
90-
entry = @entries.filter { |e| e.map_name.eql?(map_name) }
89+
def entry(map_name, system_username, database_username)
90+
entry = @entries.filter { |e| e.map_name.eql?(map_name) && e.system_username.eql?(system_username) && e.database_username.eql?(database_username) }
9191

9292
return if nil_or_empty?(entry)
9393

@@ -96,8 +96,8 @@ def entry(map_name)
9696
entry.pop
9797
end
9898

99-
def entry?(map_name)
100-
!@entries.filter { |e| e.map_name.eql?(map_name) }.empty?
99+
def entry?(map_name, system_username, database_username)
100+
!@entries.filter { |e| e.map_name.eql?(map_name) && e.system_username.eql?(system_username) && e.database_username.eql?(database_username) }.empty?
101101
end
102102

103103
def include?(entry)
@@ -120,17 +120,8 @@ def read!(file = 'pg_ident.conf', sort: true)
120120
sort! if sort
121121
end
122122

123-
def remove(entry)
124-
raise unless entry.is_a?(PgIdentFileEntry) || entry.is_a?(String)
125-
126-
remove_name = case entry
127-
when PgIdentFileEntry
128-
entry.map_name
129-
when String
130-
entry
131-
end
132-
133-
@entries.reject! { |e| e.map_name.eql?(remove_name) }
123+
def remove(map_name, system_username, database_username)
124+
@entries.reject! { |e| e.map_name.eql?(map_name) && e.system_username.eql?(system_username) && e.database_username.eql?(database_username) }
134125
end
135126

136127
def sort!
@@ -193,6 +184,7 @@ def to_s
193184
ENTRY_FIELD_FORMAT.each do |field, ljust_count|
194185
field = respond_to?(field) ? send(field) : ''
195186
field_string = field.to_s.ljust(ljust_count)
187+
field_string += ' ' unless field_string.include?(' ') || field == :comment
196188
entry_string.concat(field_string)
197189
end
198190

resources/ident.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@
5252

5353
ident_file = PostgreSQL::Cookbook::IdentHelpers::PgIdent::PgIdentFile.read(new_resource.config_file)
5454

55-
current_value_does_not_exist! unless ident_file.entry?(new_resource.map_name)
55+
current_value_does_not_exist! unless ident_file.entry?(new_resource.map_name, new_resource.system_username, new_resource.database_username)
5656

57-
entry = ident_file.entry(new_resource.map_name)
57+
entry = ident_file.entry(new_resource.map_name, new_resource.system_username, new_resource.database_username)
5858
%i(map_name system_username database_username comment).each { |p| send(p, entry.send(p)) }
5959
end
6060

@@ -65,7 +65,7 @@
6565
action :create do
6666
converge_if_changed do
6767
config_resource_init
68-
entry = config_resource.variables[:pg_ident].entry(new_resource.map_name)
68+
entry = config_resource.variables[:pg_ident].entry(new_resource.map_name, new_resource.system_username, new_resource.database_username)
6969

7070
if nil_or_empty?(entry)
7171
resource_properties = %i(map_name system_username database_username comment).map { |p| [ p, new_resource.send(p) ] }.to_h.compact
@@ -80,7 +80,7 @@
8080
action :update do
8181
converge_if_changed(:system_username, :database_username, :comment) do
8282
config_resource_init
83-
entry = config_resource.variables[:pg_ident].entry(new_resource.map_name)
83+
entry = config_resource.variables[:pg_ident].entry(new_resource.map_name, new_resource.system_username, new_resource.database_username)
8484

8585
raise Chef::Exceptions::CurrentValueDoesNotExist, "Cannot update ident entry for '#{new_resource.map_name}' as it does not exist" if nil_or_empty?(entry)
8686

@@ -91,7 +91,7 @@
9191
action :delete do
9292
config_resource_init
9393

94-
converge_by("Remove ident entry with map_name: #{new_resource.map_name}") do
95-
config_resource.variables[:pg_ident].remove(new_resource.map_name)
96-
end if config_resource.variables[:pg_ident].entry?(new_resource.map_name)
94+
converge_by("Remove ident entry where map_name: #{new_resource.map_name}, system_username: #{new_resource.system_username}, database_username: #{new_resource.database_username}") do
95+
config_resource.variables[:pg_ident].remove(new_resource.map_name, new_resource.system_username, new_resource.database_username)
96+
end if config_resource.variables[:pg_ident].entry?(new_resource.map_name, new_resource.system_username, new_resource.database_username)
9797
end

test/cookbooks/test/recipes/ident.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
end
1919

2020
user 'shef'
21+
user 'shef2'
2122

2223
postgresql_ident 'postgresl mapping' do
2324
map_name 'testmap1'
@@ -36,6 +37,14 @@
3637
notifies :reload, 'postgresql_service[postgresql]', :delayed
3738
end
3839

40+
postgresql_ident 'shef2 mapping' do
41+
map_name 'testmap2'
42+
system_username 'shef2'
43+
database_username 'sous_chef'
44+
45+
notifies :reload, 'postgresql_service[postgresql]', :delayed
46+
end
47+
3948
postgresql_ident 'shef remove mapping' do
4049
map_name 'testmap3'
4150
system_username 'shef_remove'
@@ -45,6 +54,14 @@
4554
action :delete
4655
end
4756

57+
postgresql_ident 'map with very long name' do
58+
map_name 'this_is_a_very_long_map_name_that_should_be_handled_correctly_by_the_postgresql_ident_resource'
59+
system_username 'shef'
60+
database_username 'sous_chef'
61+
62+
notifies :reload, 'postgresql_service[postgresql]', :delayed
63+
end
64+
4865
postgresql_access 'postgresql host superuser' do
4966
type 'host'
5067
database 'all'

test/integration/ident/controls/ident_map.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@
77
end
88
end
99

10+
control 'postgresql-ident-multi-map' do
11+
impact 1.0
12+
desc 'This test ensures postgres configures ident access with multiple mappings correctly'
13+
14+
describe command("sudo -u shef bash -c \"psql -U sous_chef -d test1 -c 'SELECT 1;'\"") do
15+
its('exit_status') { should eq 0 }
16+
end
17+
18+
describe command("sudo -u shef2 bash -c \"psql -U sous_chef -d test1 -c 'SELECT 1;'\"") do
19+
its('exit_status') { should eq 0 }
20+
end
21+
end
22+
1023
control 'shef and postgres roles should exist' do
1124
impact 1.0
1225
desc 'The shef & postgres database user role should exist'
@@ -18,3 +31,13 @@
1831
its('output') { should include 'sous_chef' }
1932
end
2033
end
34+
35+
control 'postgresql-ident-long-map-name' do
36+
impact 1.0
37+
desc 'This test ensures postgres configures ident access with long map names correctly'
38+
39+
describe postgres_ident_conf.where { map_name == 'this_is_a_very_long_map_name_that_should_be_handled_correctly_by_the_postgresql_ident_resource' } do
40+
its('system_username') { should cmp 'shef' }
41+
its('pg_username') { should cmp 'sous_chef' }
42+
end
43+
end

0 commit comments

Comments
 (0)