pg-ldap-sync 0.1.1 → 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1fb003bb7920f52ed32b13515630a10149a56044c43dae3d131c6d2c5d2b42ba
4
+ data.tar.gz: 973f117c4b23f726ffba5a0fec75b9388318428da44729076df441c92b6ca618
5
+ SHA512:
6
+ metadata.gz: 022c17d2bc330f6e07a09339e0e407078af90446faf0651fd1fffb62a8fb6b271acbec0c2e9e7bc9ac608535712be63c88f5cb7ef7b00b5ccc58dc9e878e9ff5
7
+ data.tar.gz: c992719c0f6dd535db928c92d5c6b7223e6f1268410a13193cbb102ecd56573aaf839e57563439cf08cc9404a7a6ec81595c4787a54784d5494e9b9c0e681c0e
Binary file
Binary file
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /temp/
10
+ Gemfile.lock
@@ -0,0 +1,17 @@
1
+ sudo: required
2
+ language: ruby
3
+ rvm:
4
+ - "2.0.0"
5
+ - ruby-head
6
+ 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\""
9
+ before_install:
10
+ - gem install bundler
11
+ - 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
17
+ script: rake test
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pg_ldap_sync.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Lars Kanis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,87 @@
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)
2
+
3
+ # Use LDAP permissions in PostgreSQL
4
+
5
+ * http://github.com/larskanis/pg-ldap-sync
6
+
7
+ ## DESCRIPTION:
8
+
9
+ LDAP is often used for a centralized user and role management in an enterprise environment.
10
+ PostgreSQL offers different authentication methods, like LDAP, SSPI, GSSAPI or SSL.
11
+ However, for any method the user must already exist in the database, before the authentication can be used.
12
+ There is currently no direct authorization of database users on LDAP.
13
+ So roles and memberships has to be administered twice.
14
+
15
+ This program helps to solve the issue by synchronizing users, groups and their memberships from LDAP to PostgreSQL.
16
+ Access to LDAP is used read-only.
17
+ `pg_ldap_sync` issues proper CREATE ROLE, DROP ROLE, GRANT and REVOKE commands to synchronize users and groups.
18
+
19
+ It is meant to be started as a cron job.
20
+
21
+ ## FEATURES:
22
+
23
+ * Configurable per YAML config file
24
+ * Can use Active Directory as LDAP-Server
25
+ * Nested groups/roles supported
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
+ * Test mode which doesn't do any changes to the DBMS
29
+ * Both LDAP and PG connections can be secured by SSL/TLS
30
+
31
+ ## REQUIREMENTS:
32
+
33
+ * Ruby-2.0+, JRuby-1.2, Rubinius-1.2 or better
34
+ * LDAP-v3 server
35
+ * PostgreSQL-server v9.0+
36
+
37
+ ## INSTALL:
38
+
39
+ Install Ruby:
40
+
41
+ * on Windows: http://rubyinstaller.org
42
+ * on Debian/Ubuntu: `apt-get install ruby libpq-dev`
43
+
44
+ Install pg-ldap-sync and required dependencies:
45
+ ```sh
46
+ gem install pg-ldap-sync
47
+ ```
48
+
49
+ ### Install from Git:
50
+ ```sh
51
+ git clone https://github.com/larskanis/pg-ldap-sync.git
52
+ cd pg-ldap-sync
53
+ bundle
54
+ rake install
55
+ ```
56
+
57
+ ## USAGE:
58
+
59
+ Create a config file based on
60
+ [config/sample-config.yaml](https://github.com/larskanis/pg-ldap-sync/blob/master/config/sample-config.yaml)
61
+ or even better
62
+ [config/sample-config2.yaml](https://github.com/larskanis/pg-ldap-sync/blob/master/config/sample-config2.yaml)
63
+
64
+ Run in test-mode:
65
+ ```sh
66
+ pg_ldap_sync -c my_config.yaml -vv -t
67
+ ```
68
+ Run in modify-mode:
69
+ ```sh
70
+ pg_ldap_sync -c my_config.yaml -vv
71
+ ```
72
+
73
+ ## TEST:
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
+ ```sh
76
+ cd pg-ldap-sync
77
+ PATH=$PATH:/usr/lib/postgresql/10/bin/ rake test
78
+ ```
79
+
80
+ ## ISSUES:
81
+
82
+ * There is currently no way to set certain user attributes in PG based on individual attributes in LDAP (expiration date etc.)
83
+
84
+
85
+ ## License
86
+
87
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,18 +1,11 @@
1
1
  # -*- ruby -*-
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
2
4
 
3
- require 'rubygems'
4
- require 'hoe'
5
-
6
- Hoe.spec 'pg-ldap-sync' do
7
- developer('Lars Kanis', 'kanis@comcard.de')
8
-
9
- extra_deps << ['net-ldap', '>= 0.2']
10
- extra_deps << ['kwalify', '>= 0.7']
11
- extra_dev_deps << ['ruby-ldapserver', '>= 0.3']
12
-
13
- self.readme_file = 'README.rdoc'
14
- spec_extras[:rdoc_options] = ['--main', readme_file, "--charset=UTF-8"]
15
- self.extra_rdoc_files << self.readme_file
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "test"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["test/**/test_*.rb"]
16
9
  end
17
10
 
18
- # vim: syntax=ruby
11
+ task :gem => :build
@@ -0,0 +1,25 @@
1
+ init:
2
+ - set PATH=C:/Ruby%ruby_version%/bin;c:/Program Files/Git/cmd;c:/Windows/system32;C:/Windows/System32/WindowsPowerShell/v1.0
3
+ - set RUBYOPT=--verbose
4
+
5
+ install:
6
+ - ver
7
+ - ruby --version
8
+ - gem --version
9
+ - gem install bundler --conservative
10
+ - bundle install
11
+
12
+ build_script:
13
+ - set PATH=C:/Program Files/PostgreSQL/%PGVER%/bin;%PATH%
14
+ - md temp
15
+ - icacls temp /grant Everyone:(OI)(CI)F /T
16
+
17
+ test_script:
18
+ - bundle exec rake test
19
+
20
+ environment:
21
+ matrix:
22
+ - ruby_version: "25-x64"
23
+ PGVER: 10
24
+ - ruby_version: "22"
25
+ PGVER: 10
@@ -7,11 +7,13 @@
7
7
  # see also: http://net-ldap.rubyforge.org/Net/LDAP.html#method-c-new
8
8
  ldap_connection:
9
9
  host: ldapserver
10
- port: 389
10
+ port: 636
11
11
  auth:
12
12
  method: :simple
13
13
  username: CN=username,OU=!Serviceaccounts,OU=company,DC=company,DC=de
14
14
  password: secret
15
+ encryption:
16
+ method: :simple_tls
15
17
 
16
18
  # Search parameters for LDAP users which should be synchronized
17
19
  ldap_users:
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pg_ldap_sync'
4
+
5
+ begin
6
+ PgLdapSync::Application.run(ARGV)
7
+ rescue PgLdapSync::ApplicationExit => ex
8
+ exit ex.exitcode
9
+ end
@@ -1,3 +1,21 @@
1
+ require "pg_ldap_sync/application"
2
+ require "pg_ldap_sync/version"
3
+
1
4
  module PgLdapSync
2
- VERSION = '0.1.1'
5
+ class LdapError < RuntimeError
6
+ end
7
+
8
+ class ApplicationExit < RuntimeError
9
+ attr_reader :exitcode
10
+
11
+ def initialize(exitcode)
12
+ @exitcode = exitcode
13
+ end
14
+ end
15
+
16
+ class InvalidConfig < ApplicationExit
17
+ end
18
+
19
+ class ErrorExit < ApplicationExit
20
+ end
3
21
  end
@@ -1,38 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require 'net/ldap'
5
4
  require 'optparse'
6
5
  require 'yaml'
7
- require 'logger'
8
6
  require 'kwalify'
9
-
10
- begin
11
- require 'pg'
12
- rescue LoadError => e
13
- begin
14
- require 'postgres'
15
- class PGconn
16
- alias initialize_before_hash_change initialize
17
- def initialize(*args)
18
- arg = args.first
19
- if args.length==1 && arg.kind_of?(Hash)
20
- initialize_before_hash_change(arg[:host], arg[:port], nil, nil, arg[:dbname], arg[:user], arg[:password])
21
- else
22
- initialize_before_hash_change(*args)
23
- end
24
- end
25
- end
26
- rescue LoadError
27
- raise e
28
- end
29
- end
30
-
31
- require 'pg_ldap_sync'
7
+ require 'pg'
8
+ require "pg_ldap_sync/logger"
32
9
 
33
10
  module PgLdapSync
34
11
  class Application
35
- class LdapError < RuntimeError; end
36
12
  attr_accessor :config_fname
37
13
  attr_accessor :log
38
14
  attr_accessor :test
@@ -58,7 +34,7 @@ class Application
58
34
  errors.each do |err|
59
35
  log.fatal "error in #{fname}: [#{err.path}] #{err.message}"
60
36
  end
61
- exit(-1)
37
+ raise InvalidConfig, 78 # EX_CONFIG
62
38
  end
63
39
  end
64
40
 
@@ -130,6 +106,9 @@ class Application
130
106
 
131
107
  PgRole = Struct.new :name, :member_names
132
108
 
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]
111
+
133
112
  def search_pg_users
134
113
  pg_users_conf = @config[:pg_users]
135
114
 
@@ -137,6 +116,7 @@ class Application
137
116
  res = pg_exec "SELECT rolname FROM pg_roles WHERE #{pg_users_conf[:filter]}"
138
117
  res.each do |tuple|
139
118
  user = PgRole.new tuple[0]
119
+ next if PG_BUILTIN_ROLES.include?(user.name)
140
120
  log.info{ "found pg-user: #{user.name.inspect}"}
141
121
  users << user
142
122
  end
@@ -149,9 +129,10 @@ class Application
149
129
  groups = []
150
130
  res = pg_exec "SELECT rolname, oid FROM pg_roles WHERE #{pg_groups_conf[:filter]}"
151
131
  res.each do |tuple|
152
- res2 = pg_exec "SELECT pr.rolname FROM pg_auth_members pam JOIN pg_roles pr ON pr.oid=pam.member WHERE pam.roleid=#{PGconn.escape(tuple[1])}"
132
+ res2 = pg_exec "SELECT pr.rolname FROM pg_auth_members pam JOIN pg_roles pr ON pr.oid=pam.member WHERE pam.roleid=#{@pgconn.escape_string(tuple[1])}"
153
133
  member_names = res2.map{|row| row[0] }
154
134
  group = PgRole.new tuple[0], member_names
135
+ next if PG_BUILTIN_ROLES.include?(group.name)
155
136
  log.info{ "found pg-group: #{group.name.inspect} with members: #{member_names.inspect}"}
156
137
  groups << group
157
138
  end
@@ -211,10 +192,21 @@ class Application
211
192
  return roles
212
193
  end
213
194
 
195
+ def try_sql(text)
196
+ begin
197
+ @pgconn.exec "SAVEPOINT try_sql;"
198
+ @pgconn.exec text
199
+ rescue PG::Error => err
200
+ @pgconn.exec "ROLLBACK TO try_sql;"
201
+
202
+ log.error{ "#{err} (#{err.class})" }
203
+ end
204
+ end
205
+
214
206
  def pg_exec_modify(sql)
215
207
  log.info{ "SQL: #{sql}" }
216
208
  unless self.test
217
- res = @pgconn.exec sql
209
+ try_sql sql
218
210
  end
219
211
  end
220
212
 
@@ -314,36 +306,46 @@ class Application
314
306
  ldap_groups = uniq_names search_ldap_groups
315
307
 
316
308
  # gather PGs users and groups
317
- @pgconn = PGconn.connect @config[:pg_connection]
318
- pg_users = uniq_names search_pg_users
319
- pg_groups = uniq_names search_pg_groups
320
-
321
- # compare LDAP to PG users and groups
322
- mroles = match_roles(ldap_users, pg_users, :user)
323
- mroles += match_roles(ldap_groups, pg_groups, :group)
324
-
325
- # compare LDAP to PG memberships
326
- mmemberships = match_memberships(ldap_users+ldap_groups, pg_users+pg_groups)
327
-
328
- # drop/revoke roles/memberships first
329
- sync_membership_to_pg(mmemberships, :revoke)
330
- sync_roles_to_pg(mroles, :drop)
331
- # create/grant roles/memberships
332
- sync_roles_to_pg(mroles, :create)
333
- sync_membership_to_pg(mmemberships, :grant)
309
+ @pgconn = PG.connect @config[:pg_connection]
310
+ begin
311
+ @pgconn.transaction do
312
+ pg_users = uniq_names search_pg_users
313
+ pg_groups = uniq_names search_pg_groups
314
+
315
+ # compare LDAP to PG users and groups
316
+ mroles = match_roles(ldap_users, pg_users, :user)
317
+ mroles += match_roles(ldap_groups, pg_groups, :group)
318
+
319
+ # compare LDAP to PG memberships
320
+ mmemberships = match_memberships(ldap_users+ldap_groups, pg_users+pg_groups)
321
+
322
+ # drop/revoke roles/memberships first
323
+ sync_membership_to_pg(mmemberships, :revoke)
324
+ sync_roles_to_pg(mroles, :drop)
325
+ # create/grant roles/memberships
326
+ sync_roles_to_pg(mroles, :create)
327
+ sync_membership_to_pg(mmemberships, :grant)
328
+ end
329
+ ensure
330
+ @pgconn.close
331
+ end
334
332
 
335
- @pgconn.close
333
+ # Determine exitcode
334
+ if log.had_errors?
335
+ raise ErrorExit, 1
336
+ end
336
337
  end
337
338
 
338
339
  def self.run(argv)
339
340
  s = self.new
340
341
  s.config_fname = '/etc/pg_ldap_sync.yaml'
341
- s.log = Logger.new(STDOUT)
342
+ s.log = Logger.new($stdout, @error_counters)
342
343
  s.log.level = Logger::ERROR
343
344
 
344
345
  OptionParser.new do |opts|
346
+ opts.version = VERSION
345
347
  opts.banner = "Usage: #{$0} [options]"
346
- opts.on("-v", "--[no-]verbose", "Increase verbose level"){ s.log.level-=1 }
348
+ opts.on("-v", "--[no-]verbose", "Increase verbose level"){|v| s.log.level += v ? -1 : 1 }
347
349
  opts.on("-c", "--config FILE", "Config file [#{s.config_fname}]", &s.method(:config_fname=))
348
350
  opts.on("-t", "--[no-]test", "Don't do any change in the database", &s.method(:test=))
349
351
 
@@ -0,0 +1,24 @@
1
+ require 'logger'
2
+
3
+ module PgLdapSync
4
+ class Logger < ::Logger
5
+ def initialize(io, counters)
6
+ super(io)
7
+ @counters = {}
8
+ end
9
+
10
+ def add(severity, *args)
11
+ @counters[severity] ||= 0
12
+ @counters[severity] += 1
13
+ super
14
+ end
15
+
16
+ def had_logged?(severity)
17
+ @counters[severity] && @counters[severity] > 0
18
+ end
19
+
20
+ def had_errors?
21
+ had_logged?(Logger::FATAL) || had_logged?(Logger::ERROR)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module PgLdapSync
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "pg_ldap_sync/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "pg-ldap-sync"
7
+ spec.version = PgLdapSync::VERSION
8
+ spec.authors = ["Lars Kanis"]
9
+ spec.email = ["lars@greiz-reinsdorf.de"]
10
+
11
+ spec.summary = %q{Use LDAP permissions in PostgreSQL}
12
+ spec.homepage = "https://github.com/larskanis/pg-ldap-sync"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+ spec.rdoc_options = %w[--main README.md --charset=UTF-8]
22
+
23
+ spec.add_runtime_dependency "net-ldap", "~> 0.16"
24
+ spec.add_runtime_dependency "kwalify", "~> 0.7"
25
+ spec.add_runtime_dependency "pg", ">= 0.14", "< 2.0"
26
+ spec.add_development_dependency "ruby-ldapserver", "~> 0.3"
27
+ spec.add_development_dependency "minitest", "~> 5.0"
28
+ spec.add_development_dependency "bundler", "~> 1.16"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "minitest-hooks", "~> 1.4"
31
+ end
metadata CHANGED
@@ -1,151 +1,206 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg-ldap-sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Lars Kanis
9
8
  autorequire:
10
- bindir: bin
11
- cert_chain: []
12
- date: 2012-11-15 00:00:00.000000000 Z
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
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=
31
+ -----END CERTIFICATE-----
32
+ date: 2018-03-13 00:00:00.000000000 Z
13
33
  dependencies:
14
34
  - !ruby/object:Gem::Dependency
15
35
  name: net-ldap
16
- requirement: &9786620 !ruby/object:Gem::Requirement
17
- none: false
36
+ requirement: !ruby/object:Gem::Requirement
18
37
  requirements:
19
- - - ! '>='
38
+ - - "~>"
20
39
  - !ruby/object:Gem::Version
21
- version: '0.2'
40
+ version: '0.16'
22
41
  type: :runtime
23
42
  prerelease: false
24
- version_requirements: *9786620
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.16'
25
48
  - !ruby/object:Gem::Dependency
26
49
  name: kwalify
27
- requirement: &9783100 !ruby/object:Gem::Requirement
28
- none: false
50
+ requirement: !ruby/object:Gem::Requirement
29
51
  requirements:
30
- - - ! '>='
52
+ - - "~>"
31
53
  - !ruby/object:Gem::Version
32
54
  version: '0.7'
33
55
  type: :runtime
34
56
  prerelease: false
35
- version_requirements: *9783100
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
36
62
  - !ruby/object:Gem::Dependency
37
- name: rdoc
38
- requirement: &9781660 !ruby/object:Gem::Requirement
39
- none: false
63
+ name: pg
64
+ requirement: !ruby/object:Gem::Requirement
40
65
  requirements:
41
- - - ~>
66
+ - - ">="
42
67
  - !ruby/object:Gem::Version
43
- version: '3.10'
44
- type: :development
68
+ version: '0.14'
69
+ - - "<"
70
+ - !ruby/object:Gem::Version
71
+ version: '2.0'
72
+ type: :runtime
45
73
  prerelease: false
46
- version_requirements: *9781660
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0.14'
79
+ - - "<"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.0'
47
82
  - !ruby/object:Gem::Dependency
48
83
  name: ruby-ldapserver
49
- requirement: &9805140 !ruby/object:Gem::Requirement
50
- none: false
84
+ requirement: !ruby/object:Gem::Requirement
51
85
  requirements:
52
- - - ! '>='
86
+ - - "~>"
53
87
  - !ruby/object:Gem::Version
54
88
  version: '0.3'
55
89
  type: :development
56
90
  prerelease: false
57
- version_requirements: *9805140
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.3'
58
96
  - !ruby/object:Gem::Dependency
59
- name: hoe
60
- requirement: &9803940 !ruby/object:Gem::Requirement
61
- none: false
97
+ name: minitest
98
+ requirement: !ruby/object:Gem::Requirement
62
99
  requirements:
63
- - - ~>
100
+ - - "~>"
64
101
  - !ruby/object:Gem::Version
65
- version: '3.0'
102
+ version: '5.0'
66
103
  type: :development
67
104
  prerelease: false
68
- version_requirements: *9803940
69
- description: ! 'LDAP is often used for a centralized user and role management
70
-
71
- in an enterprise environment. PostgreSQL offers different
72
-
73
- authentication methods, like LDAP, SSPI, GSSAPI or SSL.
74
-
75
- However, for any method the user must already exist in the database,
76
-
77
- before the authentication can be used. There is currently
78
-
79
- no direct authorization of database users on LDAP. So roles
80
-
81
- and memberships has to be administered twice.
82
-
83
-
84
- This program helps to solve the issue by synchronizing users,
85
-
86
- groups and their memberships from LDAP to PostgreSQL.
87
-
88
- Access to LDAP is used read-only. <tt>pg_ldap_sync</tt> issues proper
89
-
90
- CREATE ROLE, DROP ROLE, GRANT and REVOKE commands to synchronize
91
-
92
- users and groups.
93
-
94
-
95
- It is meant to be started as a cron job.'
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '5.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: bundler
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '1.16'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.16'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rake
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '10.0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '10.0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: minitest-hooks
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '1.4'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '1.4'
152
+ description:
96
153
  email:
97
- - kanis@comcard.de
154
+ - lars@greiz-reinsdorf.de
98
155
  executables:
99
156
  - pg_ldap_sync
100
157
  extensions: []
101
- extra_rdoc_files:
102
- - History.txt
103
- - Manifest.txt
104
- - README.rdoc
158
+ extra_rdoc_files: []
105
159
  files:
106
- - .autotest
160
+ - ".autotest"
161
+ - ".gitignore"
162
+ - ".travis.yml"
163
+ - Gemfile
107
164
  - History.txt
165
+ - LICENSE.txt
108
166
  - Manifest.txt
109
- - README.rdoc
167
+ - README.md
110
168
  - Rakefile
111
- - bin/pg_ldap_sync
169
+ - appveyor.yml
112
170
  - config/sample-config.yaml
113
171
  - config/sample-config2.yaml
114
172
  - config/schema.yaml
173
+ - exe/pg_ldap_sync
115
174
  - lib/pg_ldap_sync.rb
116
175
  - lib/pg_ldap_sync/application.rb
117
- - test/fixtures/config-ldapdb.yaml
118
- - test/fixtures/ldapdb.yaml
119
- - test/ldap_server.rb
120
- - test/test_pg_ldap_sync.rb
121
- - .gemtest
122
- homepage: http://github.com/larskanis/pg-ldap-sync
123
- licenses: []
176
+ - lib/pg_ldap_sync/logger.rb
177
+ - lib/pg_ldap_sync/version.rb
178
+ - pg-ldap-sync.gemspec
179
+ homepage: https://github.com/larskanis/pg-ldap-sync
180
+ licenses:
181
+ - MIT
182
+ metadata: {}
124
183
  post_install_message:
125
184
  rdoc_options:
126
- - --main
127
- - README.rdoc
128
- - --charset=UTF-8
185
+ - "--main"
186
+ - README.md
187
+ - "--charset=UTF-8"
129
188
  require_paths:
130
189
  - lib
131
190
  required_ruby_version: !ruby/object:Gem::Requirement
132
- none: false
133
191
  requirements:
134
- - - ! '>='
192
+ - - ">="
135
193
  - !ruby/object:Gem::Version
136
194
  version: '0'
137
195
  required_rubygems_version: !ruby/object:Gem::Requirement
138
- none: false
139
196
  requirements:
140
- - - ! '>='
197
+ - - ">="
141
198
  - !ruby/object:Gem::Version
142
199
  version: '0'
143
200
  requirements: []
144
- rubyforge_project: pg-ldap-sync
145
- rubygems_version: 1.8.10
201
+ rubyforge_project:
202
+ rubygems_version: 2.7.3
146
203
  signing_key:
147
- specification_version: 3
148
- summary: LDAP is often used for a centralized user and role management in an enterprise
149
- environment
150
- test_files:
151
- - test/test_pg_ldap_sync.rb
204
+ specification_version: 4
205
+ summary: Use LDAP permissions in PostgreSQL
206
+ test_files: []
Binary file
data/.gemtest DELETED
File without changes
@@ -1,107 +0,0 @@
1
- = Use LDAP permissions in PostgreSQL
2
-
3
- * http://github.com/larskanis/pg-ldap-sync
4
-
5
- == DESCRIPTION:
6
-
7
- LDAP is often used for a centralized user and role management
8
- in an enterprise environment. PostgreSQL offers different
9
- authentication methods, like LDAP, SSPI, GSSAPI or SSL.
10
- However, for any method the user must already exist in the database,
11
- before the authentication can be used. There is currently
12
- no direct authorization of database users on LDAP. So roles
13
- and memberships has to be administered twice.
14
-
15
- This program helps to solve the issue by synchronizing users,
16
- groups and their memberships from LDAP to PostgreSQL.
17
- Access to LDAP is used read-only. <tt>pg_ldap_sync</tt> issues proper
18
- CREATE ROLE, DROP ROLE, GRANT and REVOKE commands to synchronize
19
- users and groups.
20
-
21
- It is meant to be started as a cron job.
22
-
23
- == FEATURES:
24
-
25
- * Configurable per YAML config file
26
- * Can use Active Directory as LDAP-Server
27
- * Nested groups/roles supported
28
- * Set scope of considered users/groups on LDAP and PG side
29
- * Runs with pg.gem (C-library) or postgres-pr.gem (pure Ruby)
30
- * Test mode which doesn't do any changes to the DBMS
31
- * Both LDAP and PG connections can be secured by SSL/TLS
32
-
33
- == REQUIREMENTS:
34
-
35
- * Ruby-1.8.7, Ruby-1.9.2, JRuby-1.2, Rubinius-1.2 or better
36
- * Rubygems-1.3.5+
37
- * LDAP-v3 server
38
- * PostgreSQL-server v8.1+
39
-
40
- == INSTALL:
41
-
42
- Install Ruby and rubygems:
43
- * on Windows: http://rubyinstaller.org
44
- * on Debian/Ubuntu: <tt>apt-get install ruby rubygems</tt>
45
-
46
- Install pg-ldap-sync and a database connector for PostgreSQL:
47
- gem install pg-ldap-sync pg
48
- You may also use the pure ruby postgres-connector which is less mature,
49
- but doesn't need compilation:
50
- gem install pg-ldap-sync postgres-pr
51
-
52
- === Install from Git:
53
- git clone https://github.com/larskanis/pg-ldap-sync.git
54
- cd pg-ldap-sync
55
- gem install hoe
56
- rake install_gem
57
-
58
- == USAGE:
59
-
60
- Create a config file based on <tt>config/sample-config.yaml</tt> .
61
- Run in test-mode:
62
-
63
- pg_ldap_sync -c my_config.yaml -vv -t
64
-
65
- Run in modify-mode:
66
-
67
- pg_ldap_sync -c my_config.yaml -vv
68
-
69
-
70
- == TEST:
71
- There is a small test suite in the <tt>test</tt> directory that runs
72
- against an internal ruby-ldapserver and PostgreSQL server. Ensure gem
73
- <tt>ruby-ldapserver</tt> is installed and <tt>pg_ctl</tt>, <tt>initdb</tt> and <tt>psql</tt>
74
- commands are in the <tt>PATH</tt>. Then:
75
-
76
- cd pg-ldap-sync
77
- rake test
78
-
79
- == ISSUES:
80
- * There is currently no way to set certain user attributes in PG
81
- based on individual attributes in LDAP (expiration date etc.)
82
-
83
-
84
- == LICENSE:
85
-
86
- (The MIT License)
87
-
88
- Copyright (c) 2011 FIX
89
-
90
- Permission is hereby granted, free of charge, to any person obtaining
91
- a copy of this software and associated documentation files (the
92
- 'Software'), to deal in the Software without restriction, including
93
- without limitation the rights to use, copy, modify, merge, publish,
94
- distribute, sublicense, and/or sell copies of the Software, and to
95
- permit persons to whom the Software is furnished to do so, subject to
96
- the following conditions:
97
-
98
- The above copyright notice and this permission notice shall be
99
- included in all copies or substantial portions of the Software.
100
-
101
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
102
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
103
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
104
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
105
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
106
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
107
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'pg_ldap_sync/application'
5
-
6
- PgLdapSync::Application.run(ARGV)
@@ -1,32 +0,0 @@
1
- ---
2
- ldap_connection:
3
- host: localhost
4
- port: 1389
5
-
6
- ldap_users:
7
- base: dc=example,dc=com
8
- filter: (&(cn=*)(sAMAccountName=*))
9
- name_attribute: sAMAccountName
10
-
11
- ldap_groups:
12
- base: dc=example,dc=com
13
- filter: (member=*)
14
- name_attribute: cn
15
- member_attribute: member
16
-
17
- pg_connection:
18
- dbname: postgres
19
- host: localhost
20
- port: 54321
21
- # needed for postgres-pr:
22
- # user: insert_your_username_here
23
- # password:
24
-
25
- pg_users:
26
- filter: rolcanlogin AND NOT rolsuper
27
- create_options: LOGIN
28
-
29
- pg_groups:
30
- filter: NOT rolcanlogin
31
- create_options: NOLOGIN
32
- grant_options:
@@ -1,38 +0,0 @@
1
- ---
2
- dc=example,dc=com:
3
- cn:
4
- - Top object
5
- cn=Fred Flintstone,dc=example,dc=com:
6
- cn:
7
- - Fred Flintstone
8
- mail:
9
- - fred@bedrock.org
10
- - fred.flintstone@bedrock.org
11
- sn:
12
- - Flintstone
13
- sAMAccountName:
14
- - fred
15
- cn=Wilma Flintstone,dc=example,dc=com:
16
- cn:
17
- - Wilma Flintstone
18
- mail:
19
- - wilma@bedrock.org
20
- sAMAccountName:
21
- - wilma
22
- cn=Flintstones,dc=example,dc=com:
23
- cn:
24
- - Flintstones
25
- member:
26
- - cn=Fred Flintstone,dc=example,dc=com
27
- - cn=Wilma Flintstone,dc=example,dc=com
28
- cn=Wilmas,dc=example,dc=com:
29
- cn:
30
- - Wilmas
31
- member:
32
- - cn=Wilma Flintstone,dc=example,dc=com
33
- cn=All Users,dc=example,dc=com:
34
- cn:
35
- - All Users
36
- member:
37
- - cn=Wilmas,dc=example,dc=com
38
- - cn=Fred Flintstone,dc=example,dc=com
@@ -1,41 +0,0 @@
1
- #!/usr/local/bin/ruby -w
2
-
3
- # This is a trivial LDAP server which just stores directory entries in RAM.
4
- # It does no validation or authentication. This is intended just to
5
- # demonstrate the API, it's not for real-world use!!
6
-
7
- require 'rubygems'
8
- require 'ldap/server'
9
-
10
- # We subclass the Operation class, overriding the methods to do what we need
11
-
12
- class HashOperation < LDAP::Server::Operation
13
- def initialize(connection, messageID, hash)
14
- super(connection, messageID)
15
- @hash = hash # an object reference to our directory data
16
- end
17
-
18
- def search(basedn, scope, deref, filter)
19
- basedn.downcase!
20
-
21
- case scope
22
- when LDAP::Server::BaseObject
23
- # client asked for single object by DN
24
- obj = @hash[basedn]
25
- raise LDAP::ResultError::NoSuchObject unless obj
26
- send_SearchResultEntry(basedn, obj) if LDAP::Server::Filter.run(filter, obj)
27
-
28
- when LDAP::Server::WholeSubtree
29
- @hash.each do |dn, av|
30
- next unless dn.index(basedn, -basedn.length) # under basedn?
31
- next unless LDAP::Server::Filter.run(filter, av) # attribute filter?
32
- send_SearchResultEntry(dn, av)
33
- end
34
-
35
- else
36
- raise LDAP::ResultError::UnwillingToPerform, "OneLevel not implemented"
37
-
38
- end
39
- end
40
- end
41
-
@@ -1,119 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "test/unit"
4
- require "pg_ldap_sync/application"
5
- require 'yaml'
6
- require 'test/ldap_server'
7
- require 'fileutils'
8
-
9
- class TestPgLdapSync < Test::Unit::TestCase
10
- def log_and_run( *cmd )
11
- puts cmd.join(' ')
12
- system( *cmd )
13
- raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
14
- end
15
-
16
- def start_ldap_server
17
- yaml_fname = File.join(File.dirname(__FILE__), "fixtures/ldapdb.yaml")
18
- @directory = File.open(yaml_fname){|f| YAML::load(f.read) }
19
-
20
- # Listen for incoming LDAP connections. For each one, create a Connection
21
- # object, which will invoke a HashOperation object for each request.
22
-
23
- @ldap_server = LDAP::Server.new(
24
- :port => 1389,
25
- :nodelay => true,
26
- :listen => 10,
27
- # :ssl_key_file => "key.pem",
28
- # :ssl_cert_file => "cert.pem",
29
- # :ssl_on_connect => true,
30
- :operation_class => HashOperation,
31
- :operation_args => [@directory]
32
- )
33
- @ldap_server.run_tcpserver
34
- end
35
-
36
- def stop_ldap_server
37
- @ldap_server.stop
38
- end
39
-
40
- def start_pg_server
41
- @port = 54321
42
- ENV['PGPORT'] = @port.to_s
43
- ENV['PGHOST'] = 'localhost'
44
- unless File.exist?('temp/pg_data/PG_VERSION')
45
- FileUtils.mkdir_p 'temp/pg_data'
46
- log_and_run 'initdb', '-D', 'temp/pg_data', '--no-locale'
47
- end
48
- log_and_run 'pg_ctl', '-w', '-o', "-k.", '-D', 'temp/pg_data', 'start'
49
- log_and_run 'psql', '-e', '-c', "DROP ROLE IF EXISTS fred, wilma, \"Flintstones\", \"Wilmas\", \"All Users\"", 'postgres'
50
- end
51
-
52
- def stop_pg_server
53
- log_and_run 'pg_ctl', '-w', '-o', "-k.", '-D', 'temp/pg_data', 'stop'
54
- end
55
-
56
- def setup
57
- start_ldap_server
58
- start_pg_server
59
- end
60
-
61
- def teardown
62
- stop_ldap_server
63
- stop_pg_server
64
- end
65
-
66
- def psqlre(*args)
67
- /^\s*#{args[0]}[ |]*#{args[1]}[ |\{"]*#{args[2..-1].join('[", ]+')}["\}\s]*$/
68
- end
69
-
70
- def exec_psql_du
71
- text = if RUBY_PLATFORM=~/mingw|mswin/
72
- `psql -c \\du postgres`
73
- else
74
- `psql -c \\\\du postgres`
75
- end
76
- puts text
77
- return text
78
- end
79
-
80
- def test_sanity
81
- PgLdapSync::Application.run(%w[-c test/fixtures/config-ldapdb.yaml -vv])
82
-
83
- ENV['LC_MESSAGES'] = 'C'
84
- psql_du = exec_psql_du
85
-
86
- assert_match(psqlre('All Users','Cannot login'), psql_du)
87
- assert_match(psqlre('Flintstones','Cannot login'), psql_du)
88
- assert_match(psqlre('Wilmas','Cannot login','All Users'), psql_du)
89
- assert_match(psqlre('fred','','All Users','Flintstones'), psql_du)
90
- assert_match(psqlre('wilma','','Flintstones','Wilmas'), psql_du)
91
-
92
- # revoke membership of 'wilma' to 'Flintstones'
93
- @directory['cn=Flintstones,dc=example,dc=com']['member'].pop
94
-
95
- PgLdapSync::Application.run(%w[-c test/fixtures/config-ldapdb.yaml -vv])
96
- psql_du = exec_psql_du
97
-
98
- assert_match(psqlre('All Users','Cannot login'), psql_du)
99
- assert_match(psqlre('Flintstones','Cannot login'), psql_du)
100
- assert_match(psqlre('Wilmas','Cannot login','All Users'), psql_du)
101
- assert_match(psqlre('fred','','All Users','Flintstones'), psql_du)
102
- assert_match(psqlre('wilma','','Wilmas'), psql_du)
103
-
104
- # rename role 'wilma'
105
- @directory['cn=Wilma Flintstone,dc=example,dc=com']['sAMAccountName'] = ['Wilma Flintstone']
106
- # re-add 'Wilma' to 'Flintstones'
107
- @directory['cn=Flintstones,dc=example,dc=com']['member'] << 'cn=Wilma Flintstone,dc=example,dc=com'
108
-
109
- PgLdapSync::Application.run(%w[-c test/fixtures/config-ldapdb.yaml -vv])
110
- psql_du = exec_psql_du
111
-
112
- assert_match(psqlre('All Users','Cannot login'), psql_du)
113
- assert_match(psqlre('Flintstones','Cannot login'), psql_du)
114
- assert_match(psqlre('Wilmas','Cannot login','All Users'), psql_du)
115
- assert_match(psqlre('fred','','All Users','Flintstones'), psql_du)
116
- assert_no_match(/wilma/, psql_du)
117
- assert_match(psqlre('Wilma Flintstone','','Flintstones','Wilmas'), psql_du)
118
- end
119
- end