summaryrefslogtreecommitdiff
path: root/bin/ldap2postgres
blob: 4e26fb1afc2243fddda1a07c99135d4056226a56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/ruby

#
# Copyright (c) 2004 Peter Palfrader <peter@palfrader.org>
#
# All rights reserved.
#

require "ldap"
require "myldap"
require "yaml"
require 'postgres'
require 'optparse'


$VERBOSE = nil

def show_help(parser, code=0, io=STDOUT)
  io.puts parser
  exit(code)
end
ARGV.options do |opts|
  opts.on_tail("-h", "--help", "Display this help screen") { show_help(opts) }
  opts.on("-v", "--verbose"    , nil, "Be verbose")        { $VERBOSE = 1 }
  opts.parse!
end

def fatal(reason)
  STDERR.puts reason
  exit 1;
end

def query(pg, query)
  res = pg.exec(query)
  if (res.status != PGresult::TUPLES_OK)
    raise PGerror,"FETCH ALL command didn't return tuples properly\n"
  end
  r = res.result.collect { |tupl|
    line = Hash.new
    i = 0
    tupl.each { |fld|
      line[ res.fields[i] ] = fld
      i = i +1
    }
    line
  }
  res.clear
  r
end

@config = YAML::load( File.open( '/etc/noreply/config' ) )

ldap = MyLDAP.new(@config, "ldap2postgres")
ldap_databases = Hash.new
ldap.conn.search2(@config['basedn'], LDAP::LDAP_SCOPE_SUBTREE, '(objectclass=tnPostgreSQLdatabase)').each{ |e|
  cn = e['cn'][0]
  dn = e['dn'][0]
  ldap_databases[ cn ] = Array.new
  ldap.conn.search2(dn, LDAP::LDAP_SCOPE_SUBTREE, '(objectclass=tnPostgreSQLuser)').each{ |e2|
    uid = e2['uid'][0]
    if (uid.index(cn+"_") != 0)
      STDERR.puts "User %s in dn: %s has weird name.  Supposed to start with '%s_'. Ignoring user."%[uid, dn, cn] unless
        dn == 'ou=postgresql,o=system,ou=hosting,%s'%[config['basedn']]
    else
      ldap_databases[ e['cn'][0] ] << uid
    end
  }
}

pg = PGconn.connect('', 5432, '', '', 'template1')
pg_databases = query(pg, 'SELECT datname FROM pg_catalog.pg_database').collect { |line| line['datname'] }
pg_users     = query(pg, 'SELECT usename FROM pg_catalog.pg_user')    .collect { |line| line['usename'] }
pg_groups    = query(pg, 'SELECT groname FROM pg_catalog.pg_group')   .collect { |line| line['groname'] }


all_databases = ldap_databases.keys + pg_databases
all_databases.uniq!

all_databases.each { |dbname|
  if (! ldap_databases.has_key?(dbname) )
    puts "Additional database in Postgers: "+dbname unless %w(template0 template1 ogo).include?(dbname)
    next
  elsif (! pg_databases.include?(dbname))
    puts "Creating database and group: "+dbname
    pg.exec('CREATE DATABASE "'+dbname+'"')
    pg.exec('REVOKE ALL ON DATABASE "'+dbname+'" FROM PUBLIC')
  else 
    puts 'Common database: "'+dbname+'"' if $VERBOSE
  end
  if (pg_groups.include?(dbname))
    puts '  Common group: '+dbname if $VERBOSE
  else
    puts '  Creating group: '+dbname
    pgdb = PGconn.connect('', 5432, '', '', dbname)
    pgdb.exec('CREATE GROUP "'+dbname+'"')
    pgdb.exec('REVOKE ALL ON SCHEMA public FROM PUBLIC')
    pgdb.exec('GRANT ALL ON SCHEMA public TO GROUP "'+dbname+'"')
    pgdb.close
  end
  pg_groups.delete(dbname)
  pgdb = PGconn.connect('', 5432, '', '', dbname)
  pg_schemas = query(pgdb, 'SELECT nspname FROM pg_catalog.pg_namespace')    .collect { |line| line['nspname'] }

  ldap_databases[dbname].each { |uid|
    if (pg_users.include?(uid))
      puts "  Common user: "+uid if $VERBOSE
      # this does not hurt if the user already is in the group, but if the
      # group was droped for some reason and just created now, it readds
      # the user to gthe group
      pg.exec('ALTER GROUP "'+dbname+'" ADD USER "'+uid+'"')
    else
      puts "  Adding user: "+uid
      pg.exec('CREATE USER "'+uid+'" NOCREATEDB NOCREATEUSER IN GROUP "'+dbname+'"')
    end

    if (pg_schemas.include?(uid))
      puts '  Common schema: '+uid if $VERBOSE
    else
      puts '  Adding schema '+uid
      pgdb.exec('CREATE SCHEMA "'+uid+'" AUTHORIZATION "' +uid+'"')
      pgdb.exec('REVOKE ALL ON SCHEMA "'+uid+'" FROM PUBLIC')
    end
    pg_schemas.delete(uid)
    pg_users.delete(uid)
  }
  pg_schemas.each { |schemaname|
    puts "Additional schemas: "+schemaname unless %w(pg_toast pg_temp_1 pg_catalog public information_schema).include?(schemaname)
  }
  pgdb.close
}
pg.close

pg_users.each { |uid|
  puts "Additional user: "+uid unless %w(postgres ogo).include?(uid)
}
pg_groups.each { |gid|
  puts "Additional group: "+gid
}