This repository has been archived on 2023-12-11. You can view files and clone it, but cannot push or open issues or pull requests.
pgls/test/test_pg_ldap_sync.rb
Lars Kanis 257b1a5e49 Whole bunch of changes
Run sync within a SQL transaction, so that no partial sync happens

Don't abort on SQL errors, but print ERROR notice

Exit with code 1 when any ERRORs were logged

Silence the test suite, so that test runs are more clearly

Use PG queries instead of psql in test. This is more flexible
than parsing text outputs per Regexp.
2018-03-13 16:34:50 +01:00

195 lines
5.3 KiB
Ruby

require "minitest/autorun"
require 'minitest/hooks/test'
require "pg_ldap_sync"
require 'yaml'
require 'fileutils'
require_relative 'ldap_server'
class TestPgLdapSync < Minitest::Test
include Minitest::Hooks
@@logid = 0
def log_and_run( *cmd )
if $DEBUG
puts cmd.join(' ')
system( *cmd )
raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
else
fname = "temp/run_#{@@logid+=1}.log"
pid = Process.spawn( *cmd, [:out, :err] => [fname, "w"] )
Process.wait(pid)
unless $?.success?
$stderr.puts "Command failed: [%s]\n%s" % [cmd.join(' '), File.read(fname)]
end
File.unlink fname
raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
end
end
def start_ldap_server
@directory = [{}]
# Listen for incoming LDAP connections. For each one, create a Connection
# object, which will invoke a HashOperation object for each request.
@ldap_server = LDAP::Server.new(
:port => 1389,
:nodelay => true,
:listen => 10,
# :ssl_key_file => "key.pem",
# :ssl_cert_file => "cert.pem",
# :ssl_on_connect => true,
:operation_class => HashOperation,
:operation_args => @directory
)
@ldap_server.run_tcpserver
end
def stop_ldap_server
@ldap_server.stop
end
def start_pg_server
@port = 54321
ENV['PGPORT'] = @port.to_s
ENV['PGHOST'] = 'localhost'
unless File.exist?('temp/pg_data/PG_VERSION')
FileUtils.mkdir_p 'temp/pg_data'
log_and_run 'initdb', '-D', 'temp/pg_data', '--no-locale'
end
log_and_run 'pg_ctl', '-w', '-o', "-k.", '-D', 'temp/pg_data', 'start'
@pgconn = PG.connect dbname: 'postgres'
@pgconn.exec "SET client_min_messages to warning"
end
def stop_pg_server
@pgconn.close if @pgconn
log_and_run 'pg_ctl', '-w', '-o', "-k.", '-D', 'temp/pg_data', 'stop'
end
def before_all
super
ENV['LC_MESSAGES'] = 'C'
start_ldap_server
start_pg_server
end
def after_all
super
stop_ldap_server
stop_pg_server
end
def setup
@pgconn.exec "DROP ROLE IF EXISTS fred, wilma, \"Flintstones\", \"Wilmas\", \"All Users\", double_user"
end
def assert_role(role_name, attrs, member_of=[])
res = @pgconn.exec("SELECT * FROM pg_roles WHERE rolname = '#{@pgconn.escape_string(role_name)}'")
assert_equal 1, res.ntuples, "Role #{role_name} not found"
res2 = @pgconn.exec "SELECT pr.rolname FROM pg_auth_members pam JOIN pg_roles pr ON pr.oid=pam.roleid WHERE pam.member=#{res.to_a[0]['oid']}"
rolnames = res2.map{|t| t['rolname'] }
assert_equal member_of.sort, rolnames.sort
exp_attrs = []
exp_attrs << 'Cannot login' if res[0]['rolcanlogin'] != 't'
exp_attrs << 'Superuser' if res[0]['rolsuper'] == 't'
assert_equal attrs, exp_attrs.join(", ")
end
def refute_role(role_name)
res = @pgconn.exec("SELECT oid FROM pg_roles WHERE rolname = '#{@pgconn.escape_string(role_name)}'")
assert_equal 0, res.ntuples, "Role #{role_name} not found"
end
def exec_psql_du
text = if RUBY_PLATFORM=~/mingw|mswin/
`psql -c \\du postgres`
else
`psql -c \\\\du postgres`
end
puts text
return text
end
def load_ldap_fixture(fname)
yaml_fname = File.join(File.dirname(__FILE__), "fixtures/#{fname}.yaml")
@directory[0] = File.open(yaml_fname){|f| YAML::load(f.read) }
end
def sync_with_config(config="config-ldapdb")
PgLdapSync::Application.run(["-c", "test/fixtures/#{config}.yaml"] + ($DEBUG ? ["-vv"] : ["--no-verbose"]))
end
def sync_to_fixture(fixture: "ldapdb", config: "config-ldapdb")
load_ldap_fixture(fixture)
sync_with_config(config)
end
def sync_change
sync_to_fixture
yield(@directory)
sync_with_config
exec_psql_du if $DEBUG
end
def test_invalid_config
assert_output(/key 'ldap_users:' is required/) do
assert_raises(PgLdapSync::InvalidConfig) do
sync_with_config("config-invalid")
end
end
end
def test_base_users_groups_memberships
sync_change{}
assert_role('All Users', 'Cannot login')
assert_role('Flintstones', 'Cannot login')
assert_role('Wilmas', 'Cannot login', ['All Users'])
assert_role('fred', '', ['All Users', 'Flintstones'])
assert_role('wilma', '', ['Flintstones', 'Wilmas'])
end
def test_add_membership
sync_change do |dir|
# add 'Fred' to 'Wilmas'
@directory[0]['cn=Wilmas,dc=example,dc=com']['member'] << 'cn=Fred Flintstone,dc=example,dc=com'
end
assert_role('fred', '', ['All Users', 'Flintstones', 'Wilmas'])
end
def test_revoke_membership
sync_change do |dir|
# revoke membership of 'wilma' to 'Flintstones'
dir[0]['cn=Flintstones,dc=example,dc=com']['member'].pop
end
assert_role('wilma', '', ['Wilmas'])
end
def test_rename_role
sync_change do |dir|
# rename role 'wilma'
dir[0]['cn=Wilma Flintstone,dc=example,dc=com']['sAMAccountName'] = ['Wilma Flintstone']
end
refute_role('wilma')
assert_role('Wilma Flintstone', '', ['Flintstones', 'Wilmas'])
end
def test_dont_stop_on_error
log_and_run 'psql', '-e', '-c', "CREATE ROLE double_user LOGIN", 'postgres'
assert_raises(PgLdapSync::ErrorExit) do
sync_change do |dir|
dir[0]['cn=double_user,dc=example,dc=com'] = {'sAMAccountName' => 'double_user'}
end
end
end
end