pg-ldap-sync 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +81 -0
- data/.travis.yml +12 -9
- data/CHANGELOG.md +40 -0
- data/Gemfile +5 -0
- data/README.md +7 -6
- data/Rakefile +2 -0
- data/appveyor.yml +6 -4
- data/config/sample-config2.yaml +7 -2
- data/config/schema.yaml +6 -0
- data/lib/pg_ldap_sync/application.rb +102 -41
- data/lib/pg_ldap_sync/compat.rb +9 -0
- data/lib/pg_ldap_sync/logger.rb +9 -5
- data/lib/pg_ldap_sync/version.rb +1 -1
- data/lib/pg_ldap_sync.rb +3 -1
- data/pg-ldap-sync.gemspec +3 -2
- data.tar.gz.sig +0 -0
- metadata +45 -32
- metadata.gz.sig +0 -0
- data/History.txt +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3630b9ed2307ae5d629896016d302f8ccfee7e324ca963b2ba6dfe1cee612351
|
|
4
|
+
data.tar.gz: f2065307ea2d61d6e2498e604c3d2105248380a27039601808be6b24579ef586
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
5
|
+
- "2.4.0"
|
|
5
6
|
- ruby-head
|
|
6
7
|
env:
|
|
7
|
-
- "PGVERSION=
|
|
8
|
-
- "PGVERSION=9.
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://app.travis-ci.com/larskanis/pg-ldap-sync) [](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
|
|
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
|
-
|
|
54
|
-
|
|
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
|
-
|
|
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
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: "
|
|
23
|
-
PGVER:
|
|
24
|
-
- ruby_version: "
|
|
24
|
+
- ruby_version: "27-x64"
|
|
25
|
+
PGVER: 13
|
|
26
|
+
- ruby_version: "24"
|
|
25
27
|
PGVER: 10
|
data/config/sample-config2.yaml
CHANGED
|
@@ -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
|
|
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({})
|
|
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(
|
|
58
|
-
|
|
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 #{
|
|
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
|
-
|
|
68
|
-
|
|
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(
|
|
85
|
-
|
|
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 #{
|
|
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
|
-
|
|
95
|
-
|
|
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/
|
|
110
|
-
PG_BUILTIN_ROLES = %w[
|
|
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
|
-
|
|
238
|
-
|
|
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.
|
|
241
|
-
|
|
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
|
-
|
|
248
|
-
|
|
308
|
+
end
|
|
309
|
+
end
|
|
249
310
|
|
|
250
|
-
|
|
251
|
-
|
|
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.
|
|
254
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
403
|
+
s.log = Logger.new($stdout)
|
|
343
404
|
s.log.level = Logger::ERROR
|
|
344
405
|
|
|
345
406
|
OptionParser.new do |opts|
|
data/lib/pg_ldap_sync/logger.rb
CHANGED
|
@@ -2,23 +2,27 @@ require 'logger'
|
|
|
2
2
|
|
|
3
3
|
module PgLdapSync
|
|
4
4
|
class Logger < ::Logger
|
|
5
|
-
def initialize(io
|
|
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
|
-
|
|
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
|
data/lib/pg_ldap_sync/version.rb
CHANGED
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", "
|
|
29
|
-
spec.add_development_dependency "rake", "~>
|
|
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.
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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:
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
-
|
|
202
|
-
|
|
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
|