annotate src/savane/backend/auth_ldif_export.py @ 119:a34e97e27050

LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
author Sylvain Beucler <beuc@beuc.net>
date Sun, 02 Aug 2009 23:38:26 +0200
parents cd5e4c45265b
children 8d4b08714c90
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
1 # Replicate users and groups to an OpenLDAP directory
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
2 # Copyright (C) 2009 Sylvain Beucler
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
3 #
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
4 # This file is part of Savane.
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
5 #
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
6 # Savane is free software: you can redistribute it and/or modify
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
8 # published by the Free Software Foundation, either version 3 of the
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
9 # License, or (at your option) any later version.
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
10 #
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
11 # Savane is distributed in the hope that it will be useful,
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
15 #
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
18
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
19 # Recommended indexes:
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
20 # index uid,uidNumber,gidNumber,memberUid,shadowExpire eq
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
21
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
22 # TODO: most settings are hard-coded and need to be made configurable
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
23 # - base: dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
24 # - users ou: "users"
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
25 # - groups ou: "groups"
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
26 # - create 'organization' and 'organizationalUnit' objects?
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
27 # - min uid: 1000
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
28 # - min gid: 1000
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
29 # - default group: cn=svusers / gid=1000
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
30 # - loginShell: /usr/local/bin/sv_membersh
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
31
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
32 import sys
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
33 import codecs
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
34 import base64, binascii
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
35 from django.db import connection, models
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
36 import savane.svmain.models as svmain_models
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
37
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
38 # Convert stdout to UTF-8 - if the stdout is redirected to a file
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
39 # sys.stdout.encoding is autodetected as 'None' and you get the
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
40 # obnoxious UnicodeEncodeError python error.
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
41 sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
42
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
43 print """dn: dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
44 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
45 objectClass: dcObject
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
46 objectClass: organization
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
47 o: GNU
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
48 dc: savannah
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
49 structuralObjectClass: organization
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
50
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
51 dn: ou=users,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
52 ou: users
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
53 objectClass: organizationalUnit
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
54 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
55 structuralObjectClass: organizationalUnit
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
56
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
57 dn: ou=groups,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
58 ou: groups
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
59 objectClass: organizationalUnit
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
60 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
61 structuralObjectClass: organizationalUnit
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
62 """
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
63
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
64 # Add user admin/admin
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
65 # (REMOVE WHEN TESTING IS DONE!)
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
66 print """
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
67 dn: cn=admin,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
68 objectClass: simpleSecurityObject
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
69 objectClass: organizationalRole
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
70 cn: admin
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
71 description: LDAP administrator
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
72 userPassword:: e2NyeXB0fWt0YVZ1TFNDaEg0Wi4=
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
73 structuralObjectClass: organizationalRole
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
74 """
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
75
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
76 import MySQLdb, settings
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
77 MySQLdb.charset = 'UTF-8'
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
78 conn = MySQLdb.connect(user=settings.DATABASE_USER,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
79 passwd=settings.DATABASE_PASSWORD,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
80 db=settings.DATABASE_NAME,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
81 use_unicode=True)
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
82
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
83 # Alternatively:
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
84 #from django.db import connection
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
85 #connection.cursor() # establish connection - well looks like it does
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
86 #conn = connection.connection # MySQL-specific connection - now using mysqldb
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
87
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
88
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
89 ##
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
90 # Users
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
91 ##
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
92
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
93 max_uid = svmain_models.ExtendedUser.objects.all().aggregate(models.Max('uidNumber'))['uidNumber__max']
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
94 if max_uid < 1000: max_uid = 1000
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
95
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
96 users_with_group = {}
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
97 group_users = {}
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
98 svmain_models.Membership.query_active_memberships_raw(conn, ('group_id', 'username'))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
99 res = conn.store_result()
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
100 for row in res.fetch_row(maxrows=0, how=1):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
101 users_with_group[row['username']] = 1
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
102 if group_users.has_key(row['group_id']):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
103 group_users[row['group_id']].append(row['username'])
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
104 else:
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
105 group_users[row['group_id']] = [row['username'],]
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
106
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
107 user_saves = []
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
108 svmain_models.ExtendedUser.query_active_users_raw(conn, ('username', 'first_name', 'last_name', 'email',
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
109 'password', 'uidNumber', 'gidNumber'))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
110 res = conn.store_result()
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
111 for row in res.fetch_row(maxrows=0):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
112 (username, first_name, last_name, email, password, uidNumber, gidNumber) = row
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
113
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
114 #if uidNumber == 0: # either non-assigned, or mistakenly assigned to root
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
115 if uidNumber < 1000: # either non-assigned, or mistakenly assigned to privileged user
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
116 max_uid = max_uid + 1
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
117 user_saves.append((username, max_uid))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
118 uidNumber = max_uid
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
120 cleanup = [first_name, last_name, email]
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
121 for i in range(0, len(cleanup)):
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
122 cleanup[i] = cleanup[i].replace('\n', ' ')
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
123 cleanup[i] = cleanup[i].replace('\r', ' ')
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
124 cleanup[i] = cleanup[i].strip()
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
125 (first_name, last_name, email) = cleanup
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
126
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
127 ldap_password = '{CRYPT}!' # default = unusable password
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
128 if users_with_group.has_key(username):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
129 if password.startswith('sha1$'):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
130 # Django-specific algorithm: it sums 5-char-salt+pass instead
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
131 # of SSHA's pass+4-bytes-salt, so we can't store it in LDAP -
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
132 # /me curses django devs
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
133 pass
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
134 elif password.startswith('md5$$'):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
135 # MD5 without salt
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
136 algo, empty, hash_hex = password.split('$')
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
137 if (len(hash_hex) == 32): # filter out empty or disabled passwords
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
138 ldap_password = "{MD5}" + base64.b64encode(binascii.a2b_hex(hash_hex))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
139 elif password.startswith('md5$'):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
140 # md5$salt$ vs. {SMD5} is similar to sha1$salt$ vs. {SSHA} -
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
141 # cf. above
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
142 pass
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
143 elif password.startswith('crypt$'):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
144 # glibc crypt has improved algorithms, but where salt contains
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
145 # three '$'s, which Django doesn't support (since '$' is
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
146 # already the salt field separator). So this is only weak,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
147 # passwd-style (not shadow-style) crypt.
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
148 algo, salt_hex, hash_hex = password.split('$')
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
149 # salt_hex is 2-chars long and already prepended to hash_hex
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
150 ldap_password = "{CRYPT}" + base64.b64encode(binascii.a2b_hex(hash_hex))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
151 elif '$' not in password:
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
152 # MD5 without salt, alternate Django syntax
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
153 hash_hex = password
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
154 if (len(hash_hex) == 32): # filter out empty or disabled passwords
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
155 ldap_password = "{MD5}" + base64.b64encode(binascii.a2b_hex(hash_hex))
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
156
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
157 # Object classes:
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
158 # - posixAccount: base class for libnss-ldap/pam-ldap support
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
159 # - shadowAccount: for shadowExpire
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
160 # - inetOrgPerson: for mail and givenName, and structural class
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
161 print u"""
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
162 dn: uidNumber=%(uidNumber)d,ou=users,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
163 uid: %(username)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
164 cn:: %(full_name)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
165 sn:: %(last_name)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
166 mail: %(email)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
167 userPassword: %(ldap_password)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
168 uidNumber: %(uidNumber)d
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
169 gidNumber: %(gidNumber)d
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
170 homeDirectory: %(homedir)s
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
171 loginShell: /usr/local/bin/sv_membersh
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
172 objectClass: shadowAccount
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
173 objectClass: posixAccount
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
174 objectClass: inetOrgPerson
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
175 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
176 structuralObjectClass: inetOrgPerson""" % {
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
177 'username' : username,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
178 'full_name' : base64.b64encode((first_name + ' ' + last_name).encode('UTF-8')),
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
179 'last_name' : base64.b64encode((last_name or '-').encode('UTF-8')),
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
180 'email' : email,
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
181 'ldap_password' : ldap_password,
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
182 'uidNumber' : uidNumber,
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
183 'gidNumber' : 1000,
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
184 'homedir' : '/home/' + username[:1] + '/' + username[:2] + '/' + username,
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
185 }
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
186 # non-mandatory fields - slapadd doesn't accept empty fields apparently
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
187 if len(first_name) > 0:
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
188 print "givenName::" + base64.b64encode(first_name.encode('UTF-8'))
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
189 # disallow login for users that are not part of any group
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
190 if not users_with_group.has_key(username):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
191 # shadowExpire is a timestamp - avoid 0 as it may be
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
192 # interpreted as 'no expiration'
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
193 print "shadowExpire: 10"
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
194
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
195 ##
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
196 # Groups
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
197 ##
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
198
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
199 max_gid = svmain_models.ExtendedGroup.objects.all().aggregate(models.Max('gidNumber'))['gidNumber__max']
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
200 if max_gid < 1000: max_gid = 1000
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
201
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
202 # Create base 'svusers' group
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
203 print u"""
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
204 dn: cn=svusers,ou=groups,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
205 cn: svusers
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
206 gidNumber: 1000
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
207 objectClass: posixGroup
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
208 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
209 structuralObjectClass: posixGroup"""
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
210
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
211 # Dump groups
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
212 group_saves = []
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
213 svmain_models.ExtendedGroup.query_active_groups_raw(conn, ('group_id', 'name', 'gidNumber'))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
214 res = conn.store_result()
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
215 #for group in svmain_models.ExtendedGroup.objects.only('name'):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
216 for row in res.fetch_row(maxrows=0):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
217 (group_id, name, gidNumber) = row
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
218
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
219 if gidNumber < 1000: # either non-assigned, or mistakenly assigned to privileged user
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
220 max_gid = max_gid + 1
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
221 group_saves.append((group_id, max_gid))
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
222 gidNumber = max_gid
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
223
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
224 print u"""
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
225 dn: cn=%(name)s,ou=groups,dc=savannah,dc=gnu,dc=org
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
226 cn: %(name)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
227 gidNumber: %(gidNumber)s
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
228 objectClass: posixGroup
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
229 objectClass: top
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
230 structuralObjectClass: posixGroup""" % {
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
231 'name' : name,
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
232 'gidNumber' : gidNumber,
118
cd5e4c45265b First draft of LDAP export / population
Sylvain Beucler <beuc@beuc.net>
parents:
diff changeset
233 }
119
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
234 if group_users.has_key(group_id):
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
235 for username in group_users[group_id]:
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
236 print "memberUid: " + username
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
237
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
238 # TODO
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
239 # - user_saves
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
240 # - group_saves
a34e97e27050 LDIF export: more efficient (direct MySQL access) and cleaner (queries in the models)
Sylvain Beucler <beuc@beuc.net>
parents: 118
diff changeset
241 # with multi-line UPDATEs