pg-ldap-sync 0.1.1 → 0.2.0

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