1
|
|
2
|
import json
|
3
|
import ldap
|
4
|
import ldap.modlist
|
5
|
import random
|
6
|
|
7
|
from datetime import datetime
|
8
|
|
9
|
from mandaye import config
|
10
|
from mandaye.log import logger
|
11
|
from mandaye.backends.default import storage_conn
|
12
|
|
13
|
class Association(object):
|
14
|
"""
|
15
|
association dictionary return by the following methods:
|
16
|
{
|
17
|
'id': '', # identifier of your association (must be unique)
|
18
|
'sp_name': '', # name of the service provider (defined in the mappers)
|
19
|
'sp_login': '', # login on the service provider
|
20
|
'sp_post_values': '', # the post values for sp login form
|
21
|
'idp_unique_id:': '', # the unique identifier of the identity provider (ex.: a saml NameID)
|
22
|
'idp_name': '', # identity provide name
|
23
|
'last_connection': datetime.datetime, # last connection with this association
|
24
|
'creation_date': datetime.datetime, # creation date of this association
|
25
|
}
|
26
|
"""
|
27
|
|
28
|
@staticmethod
|
29
|
def ldap2association(ldap_object):
|
30
|
return {
|
31
|
'id': ldap_object['uniqueID'][0],
|
32
|
'sp_name': ldap_object['spName'][0],
|
33
|
'sp_login': ldap_object['spLogin'][0],
|
34
|
'sp_post_values': json.loads(ldap_object['spPostValues'][0]),
|
35
|
'idp_unique_id': ldap_object['idpUniqueID'][0],
|
36
|
'idp_name': ldap_object['idpName'][0],
|
37
|
'last_connection': datetime.strptime(
|
38
|
ldap_object['lastConnectionDate'][0][:14],
|
39
|
'%Y%m%d%H%M%S'),
|
40
|
'creation_date': datetime.strptime(
|
41
|
ldap_object['creationDate'][0][:14],
|
42
|
'%Y%m%d%H%M%S'),
|
43
|
}
|
44
|
|
45
|
@staticmethod
|
46
|
def get(sp_name, idp_unique_id, idp_name='default'):
|
47
|
""" return a list of dict with associations matching all of this options """
|
48
|
associations = []
|
49
|
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
|
50
|
filterstr='(&(objectClass=MandayeUser)(spName=%s)(idpUniqueID=%s)(idpName=%s))' % (sp_name, idp_unique_id, idp_name))
|
51
|
for result in results:
|
52
|
associations.append(Association.ldap2association(result[1]))
|
53
|
return associations
|
54
|
|
55
|
|
56
|
@staticmethod
|
57
|
def get_by_id(asso_id):
|
58
|
""" return a dict of the association with the id or None if it doesn't exist """
|
59
|
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
|
60
|
filterstr='(&(objectClass=MandayeUser)(uniqueID=%s))' %\
|
61
|
(asso_id))
|
62
|
if results:
|
63
|
return Association.ldap2association(results[0][1])
|
64
|
return None
|
65
|
|
66
|
@staticmethod
|
67
|
def has_id(asso_id):
|
68
|
""" check the given user is present in the directory """
|
69
|
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
|
70
|
filterstr='(&(objectClass=MandayeUser)(uniqueID=%s))' %\
|
71
|
(asso_id))
|
72
|
if results:
|
73
|
return True
|
74
|
return False
|
75
|
|
76
|
@staticmethod
|
77
|
def update_or_create(sp_name, sp_login, sp_post_values, idp_unique_id,
|
78
|
idp_name='default', creation_date=None, last_connection_date=None):
|
79
|
""" update or create an associtaion which match the following values
|
80
|
return the association id
|
81
|
"""
|
82
|
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
|
83
|
filterstr='(&(objectClass=MandayeUser)(spName=%s)(spLogin=%s)(idpUniqueID=%s)(idpName=%s))' %\
|
84
|
(sp_name, sp_login, idp_unique_id, idp_name))
|
85
|
if not results:
|
86
|
creation_date = creation_date or datetime.utcnow()
|
87
|
last_connection_date = last_connection_date or datetime.utcnow()
|
88
|
association = {'spName': str(sp_name),
|
89
|
'spLogin': str(sp_login),
|
90
|
'spPostValues': json.dumps(sp_post_values),
|
91
|
'idpUniqueID': str(idp_unique_id),
|
92
|
'idpName': str(idp_name),
|
93
|
'creationDate': creation_date.strftime('%Y%m%d%H%M%SZ'),
|
94
|
'lastConnectionDate': last_connection_date.strftime('%Y%m%d%H%M%SZ'),
|
95
|
'objectClass': 'MandayeUser'
|
96
|
}
|
97
|
mod_list = ldap.modlist.addModlist(association)
|
98
|
while True:
|
99
|
unique_id = random.randint(1, 5000000)
|
100
|
dn = "uniqueID=%s,%s" % (unique_id, config.ldap_base_dn)
|
101
|
try:
|
102
|
result = storage_conn.add_s(dn, mod_list)
|
103
|
except ldap.ALREADY_EXISTS:
|
104
|
continue
|
105
|
break
|
106
|
logger.info("New association %r with %r", sp_login, idp_unique_id)
|
107
|
return unique_id
|
108
|
else:
|
109
|
dn = results[0][0]
|
110
|
mod_list = [(ldap.MOD_REPLACE, 'spPostValues', json.dumps(sp_post_values))]
|
111
|
storage_conn.modify_s(dn, mod_list)
|
112
|
logger.info("Update post values for %r (%r)", sp_login, idp_unique_id)
|
113
|
return results[0][1]['uniqueID'][0]
|
114
|
|
115
|
@staticmethod
|
116
|
def delete(asso_id):
|
117
|
""" delete the association which has the following asso_id """
|
118
|
dn = "uniqueID=%s,%s" % (asso_id, config.ldap_base_dn)
|
119
|
storage_conn.delete_s(dn)
|
120
|
logger.info('Delete %r association', dn)
|
121
|
|
122
|
@staticmethod
|
123
|
def get_last_connected(sp_name, idp_unique_id, idp_name='default'):
|
124
|
""" get the last connecting association which match the parameters
|
125
|
return a dict of the association
|
126
|
"""
|
127
|
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
|
128
|
filterstr='(&(objectClass=MandayeUser)(spName=%s)(idpUniqueID=%s)(idpName=%s))' % (sp_name, idp_unique_id, idp_name))
|
129
|
if results:
|
130
|
return Association.ldap2association(results[0][1])
|
131
|
return None
|
132
|
|
133
|
@staticmethod
|
134
|
def update_last_connection(asso_id):
|
135
|
""" update the association last connection time with the current time
|
136
|
return a dict of the association
|
137
|
"""
|
138
|
last_connection = datetime.utcnow().strftime("%Y%m%d%H%M%SZ")
|
139
|
dn = "uniqueID=%s,%s" % (asso_id, config.ldap_base_dn)
|
140
|
mod_list = [(ldap.MOD_REPLACE, 'lastConnectionDate', last_connection)]
|
141
|
storage_conn.modify_s(dn, mod_list)
|
142
|
|