pg-ldap-sync 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fb003bb7920f52ed32b13515630a10149a56044c43dae3d131c6d2c5d2b42ba
4
- data.tar.gz: 973f117c4b23f726ffba5a0fec75b9388318428da44729076df441c92b6ca618
3
+ metadata.gz: 3630b9ed2307ae5d629896016d302f8ccfee7e324ca963b2ba6dfe1cee612351
4
+ data.tar.gz: f2065307ea2d61d6e2498e604c3d2105248380a27039601808be6b24579ef586
5
5
  SHA512:
6
- metadata.gz: 022c17d2bc330f6e07a09339e0e407078af90446faf0651fd1fffb62a8fb6b271acbec0c2e9e7bc9ac608535712be63c88f5cb7ef7b00b5ccc58dc9e878e9ff5
7
- data.tar.gz: c992719c0f6dd535db928c92d5c6b7223e6f1268410a13193cbb102ecd56573aaf839e57563439cf08cc9404a7a6ec81595c4787a54784d5494e9b9c0e681c0e
6
+ metadata.gz: 449792e68c3cf512209e42231b134fec4a090bb873473e4db844eb50a3f9be87cd23c07676bd80ffbf604774f6a72d1d7b508cee13d8f703577c19a4312d9975
7
+ data.tar.gz: 2bbe1be11834f35b361dc0a255cd8e02323aa2f000940efcec6e695bfa5e2653ff940c883cd6264462afda36d8125913ac012c7e89d760440345d67cd48bddd5
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ job_test_gem:
7
+ name: Test built gem
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ include:
12
+ - os: windows
13
+ ruby: "head"
14
+ PGVERSION: 15.1-1-windows-x64
15
+ PGVER: "15"
16
+ - os: windows
17
+ ruby: "2.4"
18
+ PGVERSION: 9.4.26-1-windows-x64
19
+ PGVER: "9.4"
20
+ - os: ubuntu
21
+ ruby: "head"
22
+ PGVER: "15"
23
+ - os: ubuntu
24
+ os_ver: "20.04"
25
+ ruby: "2.3"
26
+ PGVER: "9.3"
27
+ - os: macos
28
+ ruby: "head"
29
+ PGVERSION: 15.1-1-osx
30
+ PGVER: "15"
31
+
32
+ runs-on: ${{ matrix.os }}-${{ matrix.os_ver || 'latest' }}
33
+ env:
34
+ PGVERSION: ${{ matrix.PGVERSION }}
35
+ PGVER: ${{ matrix.PGVER }}
36
+
37
+ steps:
38
+ - uses: actions/checkout@v3
39
+ - name: Set up Ruby
40
+ uses: ruby/setup-ruby@v1
41
+ with:
42
+ ruby-version: ${{ matrix.ruby }}
43
+
44
+ - name: Download PostgreSQL Windows
45
+ if: matrix.os == 'windows'
46
+ run: |
47
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
48
+ function Unzip {
49
+ param([string]$zipfile, [string]$outpath)
50
+ [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
51
+ }
52
+
53
+ $(new-object net.webclient).DownloadFile("http://get.enterprisedb.com/postgresql/postgresql-$env:PGVERSION-binaries.zip", "postgresql-binaries.zip")
54
+ Unzip "postgresql-binaries.zip" "."
55
+ echo "$pwd/pgsql/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
56
+ echo "PGUSER=$env:USERNAME" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
57
+ echo "PGPASSWORD=" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
58
+ md temp
59
+ icacls temp /grant "Everyone:(OI)(CI)F" /T
60
+
61
+ - name: Download PostgreSQL Ubuntu
62
+ if: matrix.os == 'ubuntu'
63
+ run: |
64
+ echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVER" | sudo tee -a /etc/apt/sources.list.d/pgdg.list
65
+ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
66
+ sudo apt-get -y update
67
+ sudo apt-get -y --allow-downgrades install postgresql-$PGVER libpq5=$PGVER* libpq-dev=$PGVER*
68
+ echo /usr/lib/postgresql/$PGVER/bin >> $GITHUB_PATH
69
+
70
+ - name: Download PostgreSQL Macos
71
+ if: matrix.os == 'macos'
72
+ run: |
73
+ wget https://get.enterprisedb.com/postgresql/postgresql-$PGVERSION-binaries.zip && \
74
+ sudo mkdir -p /Library/PostgreSQL && \
75
+ sudo unzip postgresql-$PGVERSION-binaries.zip -d /Library/PostgreSQL/$PGVER && \
76
+ echo /Library/PostgreSQL/$PGVER/bin >> $GITHUB_PATH
77
+
78
+ - run: bundle install
79
+
80
+ - name: Run specs
81
+ run: bundle exec rake test
data/.travis.yml CHANGED
@@ -1,17 +1,20 @@
1
1
  sudo: required
2
+ dist: focal
2
3
  language: ruby
3
4
  rvm:
4
- - "2.0.0"
5
+ - "2.4.0"
5
6
  - ruby-head
6
7
  env:
7
- - "PGVERSION=10.0-1-linux-x64 PATH=\"/opt/PostgreSQL/10/bin:$PATH\""
8
- - "PGVERSION=9.3.19-1-linux-x64 PATH=\"/opt/PostgreSQL/9.3/bin:$PATH\""
8
+ - "PGVERSION=14"
9
+ - "PGVERSION=9.6"
9
10
  before_install:
10
- - gem install bundler
11
+ - gem install bundler --no-doc --conservative
11
12
  - bundle install
12
- # Download and install postgresql version to test against in /opt
13
- - |
14
- wget http://get.enterprisedb.com/postgresql/postgresql-$PGVERSION.run && \
15
- chmod +x postgresql-$PGVERSION.run && \
16
- sudo ./postgresql-$PGVERSION.run --extract-only 1 --mode unattended
13
+ # Download and install postgresql version to test against in /opt (for non-cross compile only)
14
+ - echo "deb http://apt.postgresql.org/pub/repos/apt/ ${TRAVIS_DIST}-pgdg main $PGVERSION" | sudo tee -a /etc/apt/sources.list.d/pgdg.list
15
+ - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
16
+ - sudo apt -y update
17
+ - sudo apt -y --allow-downgrades install postgresql-$PGVERSION libpq-dev
18
+ - export PATH=/usr/lib/postgresql/$PGVERSION/bin:$PATH
19
+
17
20
  script: rake test
data/CHANGELOG.md ADDED
@@ -0,0 +1,40 @@
1
+ ## 0.4.0 / 2022-12-02
2
+
3
+ * Support groups with over 1500 users in Active Directory server. #32
4
+ * Retrieve only necessary attributes from LDAP server.
5
+ * Add error text to exception, so that it's visible even if nothing is logged.
6
+ * Fix compatibility with PostgreSQL-15
7
+ * Require ruby-2.3+
8
+
9
+
10
+ ## 0.3.0 / 2022-01-18
11
+
12
+ * Add config option :bothcase_name .
13
+ This adds both spellings "Fred_Flintstone" and "fred_flintstone" as PostgreSQL users/groups.
14
+ * Update gem dependencies
15
+ * Fix compatibility with PostgreSQL-14
16
+ * Require ruby-2.4+
17
+
18
+
19
+ ## 0.2.0 / 2018-03-13
20
+
21
+ * Update gem dependencies
22
+ * Fix compatibility to pg-1.0 gem
23
+ * Add `pg_ldap_sync --version`
24
+ * Fix compatibility with PostgreSQL-10
25
+ * Don't abort on SQL errors, but print ERROR notice
26
+ * Run sync within a SQL transaction, so that no partial sync happens
27
+ * Lots of improvements to the test suite
28
+ * Run automated tests on Travis-CI and Appveyor
29
+ * Remove support for postgres-pr, since it's no longer maintained
30
+
31
+
32
+ ## 0.1.1 / 2012-11-15
33
+
34
+ * Add ability to lowercase the LDAP name for use as PG role name
35
+
36
+
37
+ ## 0.1.0 / 2011-07-13
38
+
39
+ * Birthday!
40
+
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in pg_ldap_sync.gemspec
4
4
  gemspec
5
+
6
+ group :development do
7
+ gem "debug"
8
+ gem "ruby-ldapserver", git: "https://github.com/larskanis/ruby-ldapserver/"
9
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/larskanis/pg-ldap-sync.svg?branch=master)](https://travis-ci.org/larskanis/pg-ldap-sync) [![Build status](https://ci.appveyor.com/api/projects/status/09xn9q5p64jbxtka/branch/master?svg=true)](https://ci.appveyor.com/project/larskanis/pg-ldap-sync/branch/master)
1
+ [![Build Status](https://app.travis-ci.com/larskanis/pg-ldap-sync.svg?branch=master)](https://app.travis-ci.com/larskanis/pg-ldap-sync) [![Build status](https://ci.appveyor.com/api/projects/status/09xn9q5p64jbxtka/branch/master?svg=true)](https://ci.appveyor.com/project/larskanis/pg-ldap-sync/branch/master)
2
2
 
3
3
  # Use LDAP permissions in PostgreSQL
4
4
 
@@ -24,13 +24,12 @@ It is meant to be started as a cron job.
24
24
  * Can use Active Directory as LDAP-Server
25
25
  * Nested groups/roles supported
26
26
  * Set scope of considered users/groups on LDAP and PG side
27
- * Runs with pg.gem (C-library) or postgres-pr.gem (pure Ruby)
28
27
  * Test mode which doesn't do any changes to the DBMS
29
28
  * Both LDAP and PG connections can be secured by SSL/TLS
30
29
 
31
30
  ## REQUIREMENTS:
32
31
 
33
- * Ruby-2.0+, JRuby-1.2, Rubinius-1.2 or better
32
+ * Ruby-2.0+, JRuby-1.2+
34
33
  * LDAP-v3 server
35
34
  * PostgreSQL-server v9.0+
36
35
 
@@ -50,8 +49,9 @@ Install pg-ldap-sync and required dependencies:
50
49
  ```sh
51
50
  git clone https://github.com/larskanis/pg-ldap-sync.git
52
51
  cd pg-ldap-sync
53
- bundle
54
- rake install
52
+ gem install bundler
53
+ bundle install
54
+ bundle exec rake install
55
55
  ```
56
56
 
57
57
  ## USAGE:
@@ -74,7 +74,8 @@ Run in modify-mode:
74
74
  There is a small test suite in the `test` directory that runs against an internal LDAP server and a PostgreSQL server. Ensure `pg_ctl`, `initdb` and `psql` commands are in the `PATH` like so:
75
75
  ```sh
76
76
  cd pg-ldap-sync
77
- PATH=$PATH:/usr/lib/postgresql/10/bin/ rake test
77
+ bundle install
78
+ PATH=$PATH:/usr/lib/postgresql/10/bin/ bundle exec rake test
78
79
  ```
79
80
 
80
81
  ## ISSUES:
data/Rakefile CHANGED
@@ -2,6 +2,8 @@
2
2
  require "bundler/gem_tasks"
3
3
  require "rake/testtask"
4
4
 
5
+ CLEAN.include "temp"
6
+
5
7
  Rake::TestTask.new(:test) do |t|
6
8
  t.libs << "test"
7
9
  t.libs << "lib"
data/appveyor.yml CHANGED
@@ -1,3 +1,5 @@
1
+ image: Visual Studio 2019
2
+
1
3
  init:
2
4
  - set PATH=C:/Ruby%ruby_version%/bin;c:/Program Files/Git/cmd;c:/Windows/system32;C:/Windows/System32/WindowsPowerShell/v1.0
3
5
  - set RUBYOPT=--verbose
@@ -6,7 +8,7 @@ install:
6
8
  - ver
7
9
  - ruby --version
8
10
  - gem --version
9
- - gem install bundler --conservative
11
+ - gem install bundler --no-doc --conservative
10
12
  - bundle install
11
13
 
12
14
  build_script:
@@ -19,7 +21,7 @@ test_script:
19
21
 
20
22
  environment:
21
23
  matrix:
22
- - ruby_version: "25-x64"
23
- PGVER: 10
24
- - ruby_version: "22"
24
+ - ruby_version: "27-x64"
25
+ PGVER: 13
26
+ - ruby_version: "24"
25
27
  PGVER: 10
@@ -1,7 +1,10 @@
1
1
  # With this sample config the distinction between LDAP-synchronized
2
2
  # groups/users from is done by the membership to ldap_user and
3
- # ldap_group. These two roles has to be defined manally before
4
- # pg_ldap_sync can run.
3
+ # ldap_group. These two roles have to be defined manally before
4
+ # pg_ldap_sync can run:
5
+ # CREATE GROUP ldap_group;
6
+ # CREATE USER ldap_user;
7
+ #
5
8
 
6
9
  # Connection parameters to LDAP server
7
10
  # see also: http://net-ldap.rubyforge.org/Net/LDAP.html#method-c-new
@@ -25,6 +28,8 @@ ldap_users:
25
28
  name_attribute: sAMAccountName
26
29
  # lowercase name for use as PG role name
27
30
  lowercase_name: true
31
+ # Add lowercase name *and* original name for use as PG role names (useful for migrating between case types)
32
+ bothcase_name: false
28
33
 
29
34
  # Search parameters for LDAP groups which should be synchronized
30
35
  ldap_groups:
data/config/schema.yaml CHANGED
@@ -20,6 +20,9 @@ mapping:
20
20
  "lowercase_name":
21
21
  type: bool
22
22
  required: no
23
+ "bothcase_name":
24
+ type: bool
25
+ required: no
23
26
 
24
27
  "ldap_groups":
25
28
  type: map
@@ -37,6 +40,9 @@ mapping:
37
40
  "lowercase_name":
38
41
  type: bool
39
42
  required: no
43
+ "bothcase_name":
44
+ type: bool
45
+ required: no
40
46
  "member_attribute":
41
47
  type: str
42
48
  required: yes
@@ -15,11 +15,11 @@ class Application
15
15
 
16
16
  def string_to_symbol(hash)
17
17
  if hash.kind_of?(Hash)
18
- return hash.inject({}){|h, v|
18
+ return hash.inject({}) do |h, v|
19
19
  raise "expected String instead of #{h.inspect}" unless v[0].kind_of?(String)
20
20
  h[v[0].intern] = string_to_symbol(v[1])
21
21
  h
22
- }
22
+ end
23
23
  else
24
24
  return hash
25
25
  end
@@ -52,20 +52,33 @@ class Application
52
52
 
53
53
  def search_ldap_users
54
54
  ldap_user_conf = @config[:ldap_users]
55
+ name_attribute = ldap_user_conf[:name_attribute]
55
56
 
56
57
  users = []
57
- res = @ldap.search(:base => ldap_user_conf[:base], :filter => ldap_user_conf[:filter]) do |entry|
58
- name = entry[ldap_user_conf[:name_attribute]].first
58
+ res = @ldap.search(
59
+ base: ldap_user_conf[:base],
60
+ filter: ldap_user_conf[:filter],
61
+ attributes: [name_attribute, :dn]
62
+ ) do |entry|
63
+ name = entry[name_attribute].first
59
64
 
60
65
  unless name
61
- log.warn "user attribute #{ldap_user_conf[:name_attribute].inspect} not defined for #{entry.dn}"
66
+ log.warn "user attribute #{name_attribute.inspect} not defined for #{entry.dn}"
62
67
  next
63
68
  end
64
- name.downcase! if ldap_user_conf[:lowercase_name]
65
-
66
69
  log.info "found user-dn: #{entry.dn}"
67
- user = LdapRole.new name, entry.dn
68
- users << user
70
+
71
+ names = if ldap_user_conf[:bothcase_name]
72
+ [name, name.downcase].uniq
73
+ elsif ldap_user_conf[:lowercase_name]
74
+ [name.downcase]
75
+ else
76
+ [name]
77
+ end
78
+
79
+ names.each do |n|
80
+ users << LdapRole.new(n, entry.dn)
81
+ end
69
82
  entry.each do |attribute, values|
70
83
  log.debug " #{attribute}:"
71
84
  values.each do |value|
@@ -77,22 +90,70 @@ class Application
77
90
  return users
78
91
  end
79
92
 
93
+ def retrieve_array_attribute(entry, attribute_name)
94
+ array = entry[attribute_name]
95
+ if array.empty?
96
+ # Possibly an attribute, which must be retrieved in several ranges
97
+
98
+ ranged_attr = entry.attribute_names.find { |n| n =~ /\A#{Regexp.escape(attribute_name)};range=/ }
99
+ if ranged_attr
100
+ entry_dn = entry.dn
101
+
102
+ loop do
103
+ array += entry[ranged_attr]
104
+ log.debug "retrieved attribute range #{ranged_attr.inspect} of dn #{entry_dn}"
105
+
106
+ if ranged_attr =~ /;range=\d\-\*\z/
107
+ break
108
+ end
109
+
110
+ attribute_with_range = ranged_attr.to_s.gsub(/;range=.*/, ";range=#{array.size}-*")
111
+ entry = @ldap.search(
112
+ base: entry_dn,
113
+ scope: Net::LDAP::SearchScope_BaseObject,
114
+ attributes: attribute_with_range).first
115
+
116
+ ranged_attr = entry.attribute_names.find { |n| n =~ /\A#{Regexp.escape(attribute_name)};range=/ }
117
+ end
118
+ end
119
+ else
120
+ # Values already received -> No ranged attribute
121
+ end
122
+ return array
123
+ end
124
+
80
125
  def search_ldap_groups
81
126
  ldap_group_conf = @config[:ldap_groups]
127
+ name_attribute = ldap_group_conf[:name_attribute]
128
+ member_attribute = ldap_group_conf[:member_attribute]
82
129
 
83
130
  groups = []
84
- res = @ldap.search(:base => ldap_group_conf[:base], :filter => ldap_group_conf[:filter]) do |entry|
85
- name = entry[ldap_group_conf[:name_attribute]].first
131
+ res = @ldap.search(
132
+ base: ldap_group_conf[:base],
133
+ filter: ldap_group_conf[:filter],
134
+ attributes: [name_attribute, member_attribute, :dn]
135
+ ) do |entry|
136
+ name = entry[name_attribute].first
86
137
 
87
138
  unless name
88
- log.warn "user attribute #{ldap_group_conf[:name_attribute].inspect} not defined for #{entry.dn}"
139
+ log.warn "user attribute #{name_attribute.inspect} not defined for #{entry.dn}"
89
140
  next
90
141
  end
91
- name.downcase! if ldap_group_conf[:lowercase_name]
92
142
 
93
143
  log.info "found group-dn: #{entry.dn}"
94
- group = LdapRole.new name, entry.dn, entry[ldap_group_conf[:member_attribute]]
95
- groups << group
144
+
145
+ names = if ldap_group_conf[:bothcase_name]
146
+ [name, name.downcase].uniq
147
+ elsif ldap_group_conf[:lowercase_name]
148
+ [name.downcase]
149
+ else
150
+ [name]
151
+ end
152
+
153
+ names.each do |n|
154
+ group_members = retrieve_array_attribute(entry, member_attribute)
155
+ groups << LdapRole.new(n, entry.dn, group_members)
156
+ end
96
157
  entry.each do |attribute, values|
97
158
  log.debug " #{attribute}:"
98
159
  values.each do |value|
@@ -106,8 +167,8 @@ class Application
106
167
 
107
168
  PgRole = Struct.new :name, :member_names
108
169
 
109
- # List of default roles taken from https://www.postgresql.org/docs/current/static/default-roles.html
110
- PG_BUILTIN_ROLES = %w[ pg_signal_backend pg_monitor pg_read_all_settings pg_read_all_stats pg_stat_scan_tables]
170
+ # List of default roles taken from https://www.postgresql.org/docs/current/predefined-roles.html
171
+ PG_BUILTIN_ROLES = %w[ pg_read_all_data pg_write_all_data pg_read_all_settings pg_read_all_stats pg_stat_scan_tables pg_monitor pg_database_owner pg_signal_backend pg_read_server_files pg_write_server_files pg_execute_server_program pg_checkpoint]
111
172
 
112
173
  def search_pg_users
113
174
  pg_users_conf = @config[:pg_users]
@@ -183,12 +244,12 @@ class Application
183
244
  r.type = type
184
245
  end
185
246
 
186
- log.info{
247
+ log.info do
187
248
  roles.each do |role|
188
249
  log.debug{ "#{role.state} #{role.type}: #{role.name}" }
189
250
  end
190
251
  "#{type} stat: create: #{roles.count{|r| r.state==:create }} drop: #{roles.count{|r| r.state==:drop }} keep: #{roles.count{|r| r.state==:keep }}"
191
- }
252
+ end
192
253
  return roles
193
254
  end
194
255
 
@@ -234,42 +295,42 @@ class Application
234
295
  MatchedMembership = Struct.new :role_name, :has_member, :state
235
296
 
236
297
  def match_memberships(ldap_roles, pg_roles)
237
- ldap_by_dn = ldap_roles.inject({}){|h,r| h[r.dn] = r; h }
238
- ldap_by_m2m = ldap_roles.inject([]){|a,r|
298
+ hash_of_arrays = Hash.new { |h, k| h[k] = [] }
299
+ ldap_by_dn = ldap_roles.inject(hash_of_arrays){|h,r| h[r.dn] << r; h }
300
+ ldap_by_m2m = ldap_roles.inject([]) do |a,r|
239
301
  next a unless r.member_dns
240
- a + r.member_dns.map{|dn|
241
- if has_member=ldap_by_dn[dn]
302
+ a + r.member_dns.flat_map do |dn|
303
+ has_members = ldap_by_dn[dn]
304
+ log.warn{"ldap member with dn #{dn} is unknown"} if has_members.empty?
305
+ has_members.map do |has_member|
242
306
  [r.name, has_member.name]
243
- else
244
- log.warn{"ldap member with dn #{dn} is unknown"}
245
- nil
246
307
  end
247
- }.compact
248
- }
308
+ end
309
+ end
249
310
 
250
- pg_by_name = pg_roles.inject({}){|h,r| h[r.name] = r; h }
251
- pg_by_m2m = pg_roles.inject([]){|a,r|
311
+ hash_of_arrays = Hash.new { |h, k| h[k] = [] }
312
+ pg_by_name = pg_roles.inject(hash_of_arrays){|h,r| h[r.name] << r; h }
313
+ pg_by_m2m = pg_roles.inject([]) do |a,r|
252
314
  next a unless r.member_names
253
- a + r.member_names.map{|name|
254
- if has_member=pg_by_name[name]
315
+ a + r.member_names.flat_map do |name|
316
+ has_members = pg_by_name[name]
317
+ log.warn{"pg member with name #{name} is unknown"} if has_members.empty?
318
+ has_members.map do |has_member|
255
319
  [r.name, has_member.name]
256
- else
257
- log.warn{"pg member with name #{name} is unknown"}
258
- nil
259
320
  end
260
- }.compact
261
- }
321
+ end
322
+ end
262
323
 
263
324
  memberships = (ldap_by_m2m & pg_by_m2m).map{|r,mo| MatchedMembership.new r, mo, :keep }
264
325
  memberships += (ldap_by_m2m - pg_by_m2m).map{|r,mo| MatchedMembership.new r, mo, :grant }
265
326
  memberships += (pg_by_m2m - ldap_by_m2m).map{|r,mo| MatchedMembership.new r, mo, :revoke }
266
327
 
267
- log.info{
328
+ log.info do
268
329
  memberships.each do |membership|
269
330
  log.debug{ "#{membership.state} #{membership.role_name} to #{membership.has_member}" }
270
331
  end
271
332
  "membership stat: grant: #{memberships.count{|u| u.state==:grant }} revoke: #{memberships.count{|u| u.state==:revoke }} keep: #{memberships.count{|u| u.state==:keep }}"
272
- }
333
+ end
273
334
  return memberships
274
335
  end
275
336
 
@@ -332,14 +393,14 @@ class Application
332
393
 
333
394
  # Determine exitcode
334
395
  if log.had_errors?
335
- raise ErrorExit, 1
396
+ raise ErrorExit.new(1, log.first_error)
336
397
  end
337
398
  end
338
399
 
339
400
  def self.run(argv)
340
401
  s = self.new
341
402
  s.config_fname = '/etc/pg_ldap_sync.yaml'
342
- s.log = Logger.new($stdout, @error_counters)
403
+ s.log = Logger.new($stdout)
343
404
  s.log.level = Logger::ERROR
344
405
 
345
406
  OptionParser.new do |opts|
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class Hash
4
+ def transform_keys
5
+ map do |k, v|
6
+ [yield(k), v]
7
+ end.to_h
8
+ end unless method_defined? :transform_keys
9
+ end
@@ -2,23 +2,27 @@ require 'logger'
2
2
 
3
3
  module PgLdapSync
4
4
  class Logger < ::Logger
5
- def initialize(io, counters)
5
+ def initialize(io)
6
6
  super(io)
7
7
  @counters = {}
8
8
  end
9
9
 
10
- def add(severity, *args)
11
- @counters[severity] ||= 0
12
- @counters[severity] += 1
10
+ def add(severity, *args, &block)
13
11
  super
12
+ return unless [Logger::FATAL, Logger::ERROR].include?(severity)
13
+ @counters[severity] ||= block ? block.call : args.first
14
14
  end
15
15
 
16
16
  def had_logged?(severity)
17
- @counters[severity] && @counters[severity] > 0
17
+ !!@counters[severity]
18
18
  end
19
19
 
20
20
  def had_errors?
21
21
  had_logged?(Logger::FATAL) || had_logged?(Logger::ERROR)
22
22
  end
23
+
24
+ def first_error
25
+ @counters[Logger::FATAL] || @counters[Logger::ERROR]
26
+ end
23
27
  end
24
28
  end
@@ -1,3 +1,3 @@
1
1
  module PgLdapSync
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/pg_ldap_sync.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "pg_ldap_sync/application"
2
+ require "pg_ldap_sync/compat"
2
3
  require "pg_ldap_sync/version"
3
4
 
4
5
  module PgLdapSync
@@ -8,7 +9,8 @@ module PgLdapSync
8
9
  class ApplicationExit < RuntimeError
9
10
  attr_reader :exitcode
10
11
 
11
- def initialize(exitcode)
12
+ def initialize(exitcode, error=nil)
13
+ super(error)
12
14
  @exitcode = exitcode
13
15
  end
14
16
  end
data/pg-ldap-sync.gemspec CHANGED
@@ -19,13 +19,14 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
  spec.rdoc_options = %w[--main README.md --charset=UTF-8]
22
+ spec.required_ruby_version = ">= 2.3"
22
23
 
23
24
  spec.add_runtime_dependency "net-ldap", "~> 0.16"
24
25
  spec.add_runtime_dependency "kwalify", "~> 0.7"
25
26
  spec.add_runtime_dependency "pg", ">= 0.14", "< 2.0"
26
27
  spec.add_development_dependency "ruby-ldapserver", "~> 0.3"
27
28
  spec.add_development_dependency "minitest", "~> 5.0"
28
- spec.add_development_dependency "bundler", "~> 1.16"
29
- spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "bundler", ">= 1.16", "< 3.0"
30
+ spec.add_development_dependency "rake", "~> 13.0"
30
31
  spec.add_development_dependency "minitest-hooks", "~> 1.4"
31
32
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,35 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg-ldap-sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lars Kanis
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
- MIIDLjCCAhagAwIBAgIBBjANBgkqhkiG9w0BAQsFADA9MQ4wDAYDVQQDDAVrYW5p
14
- czEXMBUGCgmSJomT8ixkARkWB2NvbWNhcmQxEjAQBgoJkiaJk/IsZAEZFgJkZTAe
15
- Fw0xODAzMDUwOTEzNDdaFw0xOTAzMDUwOTEzNDdaMD0xDjAMBgNVBAMMBWthbmlz
16
- MRcwFQYKCZImiZPyLGQBGRYHY29tY2FyZDESMBAGCgmSJomT8ixkARkWAmRlMIIB
17
- IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApop+rNmg35bzRugZ21VMGqI6
18
- HGzPLO4VHYncWn/xmgPU/ZMcZdfj6MzIaZJ/czXyt4eHpBk1r8QOV3gBXnRXEjVW
19
- 9xi+EdVOkTV2/AVFKThcbTAQGiF/bT1n2M+B1GTybRzMg6hyhOJeGPqIhLfJEpxn
20
- lJi4+ENAVT4MpqHEAGB8yFoPC0GqiOHQsdHxQV3P3c2OZqG+yJey74QtwA2tLcLn
21
- Q53c63+VLGsOjODl1yPn/2ejyq8qWu6ahfTxiIlSar2UbwtaQGBDFdb2CXgEufXT
22
- L7oaPxlmj+Q2oLOfOnInd2Oxop59HoJCQPsg8f921J43NCQGA8VHK6paxIRDLQID
23
- AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUvgTdT7fe
24
- x17ugO3IOsjEJwW7KP4wDQYJKoZIhvcNAQELBQADggEBAEr2BqIKipd4rQ++Qmxw
25
- TU0prQzjlcDLxhQAX4JgmTMbSg8uO+cSvgsROcHfA1Cpo8VDDkZMoGISmfzmMegL
26
- QvZJp0Fr1TpeVxexhZq+MnC6OgqJSBfbhHh6DCMX1QAy8fvNzcmEOwRA5d3BYmWK
27
- bM8sBrAJGwrNRimekkTGTpYh5+gpiXm9JY07swwL2tR/faH/17IOXxJQ9sMXHNQU
28
- In/Pt5lKfMn+h+Ts8GhM91pEJnfwmBc0ksG8tDXAKAAUWIeizjL73bwtiXXeRRlA
29
- KtR70pH8rQHNxC2EvqVpBmRChJgWVMlfQofqhU2QK4s+5h52OHGZqMqCAeJ5taum
30
- Lvw=
13
+ MIIETTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1sYXJz
14
+ L0RDPWdyZWl6LXJlaW5zZG9yZi9EQz1kZTAeFw0yMjAyMTQxMzMwNTZaFw0yMzAy
15
+ MTQxMzMwNTZaMCgxJjAkBgNVBAMMHWxhcnMvREM9Z3JlaXotcmVpbnNkb3JmL0RD
16
+ PWRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwum6Y1KznfpzXOT/
17
+ mZgJTBbxZuuZF49Fq3K0WA67YBzNlDv95qzSp7V/7Ek3NCcnT7G+2kSuhNo1FhdN
18
+ eSDO/moYebZNAcu3iqLsuzuULXPLuoU0GsMnVMqV9DZPh7cQHE5EBZ7hlzDBK7k/
19
+ 8nBMvR0mHo77kIkapHc26UzVq/G0nKLfDsIHXVylto3PjzOumjG6GhmFN4r3cP6e
20
+ SDfl1FSeRYVpt4kmQULz/zdSaOH3AjAq7PM2Z91iGwQvoUXMANH2v89OWjQO/NHe
21
+ JMNDFsmHK/6Ji4Kk48Z3TyscHQnipAID5GhS1oD21/WePdj7GhmbF5gBzkV5uepd
22
+ eJQPgWGwrQW/Z2oPjRuJrRofzWfrMWqbOahj9uth6WSxhNexUtbjk6P8emmXOJi5
23
+ chQPnWX+N3Gj+jjYxqTFdwT7Mj3pv1VHa+aNUbqSPpvJeDyxRIuo9hvzDaBHb/Cg
24
+ 9qRVcm8a96n4t7y2lrX1oookY6bkBaxWOMtWlqIprq8JZXM9AgMBAAGjgYEwfzAJ
25
+ BgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUOIdbSMr3VFrTCO9/cTM0
26
+ 0exHzBcwIgYDVR0RBBswGYEXbGFyc0BncmVpei1yZWluc2RvcmYuZGUwIgYDVR0S
27
+ BBswGYEXbGFyc0BncmVpei1yZWluc2RvcmYuZGUwDQYJKoZIhvcNAQELBQADggGB
28
+ AFWP7F/y3Oq3NgrqUOnjKOeDaBa7AqNhHS+PZg+C90lnJzMgOs4KKgZYxqSQVSab
29
+ SCEmzIO/StkXY4NpJ4fYLrHemf/fJy1wPyu+fNdp5SEEUwEo+2toRFlzTe4u4LdS
30
+ QC636nPPTMt8H3xz2wf/lUIUeo2Qc95Qt2BQM465ibbG9kmA3c7Sopx6yOabYOAl
31
+ KPRbOSEPiWYcF9Suuz8Gdf8jxEtPlnZiwRvnYJ+IHMq3XQCJWPpMzdDMbtlgHbXE
32
+ vq1zOTLMSYAS0UB3uionR4yo1hLz60odwkCm7qf0o2Ci/5OjtB0a89VuyqRU2vUJ
33
+ QH95WBjDJ6lCCW7J0mrMPnJQSUFTmufsU6jOChvPaCeAzW1YwrsP/YKnvwueG7ip
34
+ VOdW6RitjtFxhS7evRL0201+KUvLz12zZWWjOcujlQs64QprxOtiv/MiisKb1Ng+
35
+ oL1mUdzB8KrZL4/WbG5YNX6UTtJbIOu9qEFbBAy4/jtIkJX+dlNoFwd4GXQW1YNO
36
+ nA==
31
37
  -----END CERTIFICATE-----
32
- date: 2018-03-13 00:00:00.000000000 Z
38
+ date: 2022-12-02 00:00:00.000000000 Z
33
39
  dependencies:
34
40
  - !ruby/object:Gem::Dependency
35
41
  name: net-ldap
@@ -111,30 +117,36 @@ dependencies:
111
117
  name: bundler
112
118
  requirement: !ruby/object:Gem::Requirement
113
119
  requirements:
114
- - - "~>"
120
+ - - ">="
115
121
  - !ruby/object:Gem::Version
116
122
  version: '1.16'
123
+ - - "<"
124
+ - !ruby/object:Gem::Version
125
+ version: '3.0'
117
126
  type: :development
118
127
  prerelease: false
119
128
  version_requirements: !ruby/object:Gem::Requirement
120
129
  requirements:
121
- - - "~>"
130
+ - - ">="
122
131
  - !ruby/object:Gem::Version
123
132
  version: '1.16'
133
+ - - "<"
134
+ - !ruby/object:Gem::Version
135
+ version: '3.0'
124
136
  - !ruby/object:Gem::Dependency
125
137
  name: rake
126
138
  requirement: !ruby/object:Gem::Requirement
127
139
  requirements:
128
140
  - - "~>"
129
141
  - !ruby/object:Gem::Version
130
- version: '10.0'
142
+ version: '13.0'
131
143
  type: :development
132
144
  prerelease: false
133
145
  version_requirements: !ruby/object:Gem::Requirement
134
146
  requirements:
135
147
  - - "~>"
136
148
  - !ruby/object:Gem::Version
137
- version: '10.0'
149
+ version: '13.0'
138
150
  - !ruby/object:Gem::Dependency
139
151
  name: minitest-hooks
140
152
  requirement: !ruby/object:Gem::Requirement
@@ -149,7 +161,7 @@ dependencies:
149
161
  - - "~>"
150
162
  - !ruby/object:Gem::Version
151
163
  version: '1.4'
152
- description:
164
+ description:
153
165
  email:
154
166
  - lars@greiz-reinsdorf.de
155
167
  executables:
@@ -158,10 +170,11 @@ extensions: []
158
170
  extra_rdoc_files: []
159
171
  files:
160
172
  - ".autotest"
173
+ - ".github/workflows/ci.yml"
161
174
  - ".gitignore"
162
175
  - ".travis.yml"
176
+ - CHANGELOG.md
163
177
  - Gemfile
164
- - History.txt
165
178
  - LICENSE.txt
166
179
  - Manifest.txt
167
180
  - README.md
@@ -173,6 +186,7 @@ files:
173
186
  - exe/pg_ldap_sync
174
187
  - lib/pg_ldap_sync.rb
175
188
  - lib/pg_ldap_sync/application.rb
189
+ - lib/pg_ldap_sync/compat.rb
176
190
  - lib/pg_ldap_sync/logger.rb
177
191
  - lib/pg_ldap_sync/version.rb
178
192
  - pg-ldap-sync.gemspec
@@ -180,7 +194,7 @@ homepage: https://github.com/larskanis/pg-ldap-sync
180
194
  licenses:
181
195
  - MIT
182
196
  metadata: {}
183
- post_install_message:
197
+ post_install_message:
184
198
  rdoc_options:
185
199
  - "--main"
186
200
  - README.md
@@ -191,16 +205,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
205
  requirements:
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
- version: '0'
208
+ version: '2.3'
195
209
  required_rubygems_version: !ruby/object:Gem::Requirement
196
210
  requirements:
197
211
  - - ">="
198
212
  - !ruby/object:Gem::Version
199
213
  version: '0'
200
214
  requirements: []
201
- rubyforge_project:
202
- rubygems_version: 2.7.3
203
- signing_key:
215
+ rubygems_version: 3.3.7
216
+ signing_key:
204
217
  specification_version: 4
205
218
  summary: Use LDAP permissions in PostgreSQL
206
219
  test_files: []
metadata.gz.sig CHANGED
Binary file
data/History.txt DELETED
@@ -1,8 +0,0 @@
1
- === 0.1.1 / 2012-11-15
2
-
3
- * Add ability to lowercase the LDAP name for use as PG role name
4
-
5
- === 0.1.0 / 2011-07-13
6
-
7
- * Birthday!
8
-