pg-ldap-sync 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
-