View Javadoc

1   /*
2    * LDAPGroup.java
3    *
4    * Created on May 25, 2004, 11:57 AM
5    */
6   
7   package gov.bnl.gums;
8   
9   import java.util.*;
10  import javax.naming.*;
11  import javax.naming.directory.*;
12  import org.apache.commons.logging.*;
13  
14  /*** A group of users defined by an LDAP VO.
15   * <p>
16   * The query should be :
17   * <ul>
18   *   <li>A People ou (i.e. ou=People,o=atlas,dc=eu-datagrid,dc=org). All the 
19   *   object found in that category will have to have a 'description' attribute
20   *   which will contain the certificate DN</li>
21   *   <li>A group ou (i.e. ou=usatlas,o=atlas,dc=eu-datagrid,dc=org). The ou
22   *   object will need to have a 'member' property with the list of people in 
23   *   the VO that are in the group. Each member will be an object in
24   *   ou=People</li>
25   *   <li>A root o (i.e. o=atlas,dc=eu-datagrid,dc=org). A ou=People object will
26   *   be expected, and it will behave like the first option</li>
27   * </ul>
28   *
29   * @author  carcassi
30   */
31  public class LDAPGroup implements UserGroup {
32      private Log log = LogFactory.getLog(LDAPGroup.class);
33      private Log resourceAdminLog = LogFactory.getLog(GUMS.resourceAdminLog);
34      
35      private UserGroupDB db;
36      private String name;
37      private PersistenceFactory persistanceFactory;    
38      
39      public java.util.List getMemberList() {
40          return db.retrieveMembers();
41      }
42      
43      public String getName() {
44          return name;
45      }
46      
47      public void setName(String name) {
48          this.name = name;
49      }
50      
51      public boolean isInGroup(GridUser user) {
52          return db.isMemberInGroup(user);
53      }
54      
55      public void updateMembers() {
56          db.loadUpdatedList(retrieveMembers());
57      }
58      
59      private String server;
60      private String query;
61      
62      /***
63       * Returns the list of member retrieved from the LDAP server. The members are not saved in the database.
64       * @return A list of VOEntry objects representing the members.
65       */
66      private List retrieveMembers() {
67          java.util.Properties jndiProperties = new java.util.Properties();
68          jndiProperties.put("java.naming.provider.url","ldap://"+server);
69          jndiProperties.put("java.naming.factory.initial","com.sun.jndi.ldap.LdapCtxFactory");
70          log.info("Retrieving members from '" + jndiProperties.getProperty("java.naming.provider.url") +
71                   "'  '" + query + "'");
72          try {
73              javax.naming.directory.DirContext jndiCtx = new javax.naming.directory.InitialDirContext(jndiProperties);
74              
75              if (query.startsWith("ou=People,")) {
76                  String voRoot = query.substring(query.indexOf(',')+1);
77                  DirContext rootCtx = (DirContext) jndiCtx.lookup(voRoot);
78                  return retrieveVOMembers(rootCtx);
79              } else if (query.startsWith("ou=")) {
80                  Attributes atts = jndiCtx.getAttributes(query);
81                  Attribute members = atts.get("member");
82                  if (members == null) {
83                      throw new RuntimeException("Couldn't retrieve the list of members from the LDAP group: missing attribute member");
84                  }
85                  String voRoot = query.substring(query.indexOf(',')+1);
86                  DirContext rootCtx = (DirContext) jndiCtx.lookup(voRoot);
87                  return retrieveGroupMembers(rootCtx, members);
88              } else if (query.startsWith("o=")) {
89                  DirContext rootCtx = (DirContext) jndiCtx.lookup(query);
90                  return retrieveVOMembers(rootCtx);
91              } else {
92                  throw new IllegalArgumentException("The query is not understood by the LDAP group. It is expected to start with \"ou=...\" or \"o=...\"");
93              }
94  
95          } catch (javax.naming.NamingException e) {
96              String message = "Couldn't retrieve users from LDAP server: " + e;
97  /*            if (e.getRootCause() != null) {
98                  message += " caused by [" + e.getRootCause().getMessage() + "]";
99              }*/
100             log.error("Couldn't retrieve LDAP users: ", e);
101             throw new RuntimeException(message, e);
102         }
103     }
104     
105     private List retrieveVOMembers(DirContext rootCtx) throws NamingException {
106         Map people = retrievePeopleMap(rootCtx);
107         List list = new ArrayList(people.values());
108         if (list.isEmpty()) {
109             resourceAdminLog.warn("The following group returned no members: " + this);
110         }
111         Iterator iter = list.iterator();
112         List users = new ArrayList();
113         while (iter.hasNext()) {
114             String dn = (String) iter.next();
115             users.add(new GridUser(dn, null));
116         }
117         if (list.isEmpty()) {
118             resourceAdminLog.warn("The following group returned no members: " + this);
119         }
120         return users;
121     }
122     
123     private List retrieveGroupMembers(DirContext rootCtx, Attribute members) throws javax.naming.NamingException {
124         Map people = retrievePeopleMap(rootCtx);
125         NamingEnumeration names = members.getAll();
126         List list = new ArrayList();
127         while (names.hasMore()) {
128             // Converting the people to the DN, by looking up the person description attribute
129             String ldapName = (String) names.next();
130             ldapName = ldapName.trim();
131             String certDN = (String) people.get(ldapName);
132             if (certDN == null) {
133                 resourceAdminLog.warn("Member of a LDAP VO group not mapped to any certificate: '" + ldapName + "'");
134             } else {
135                 list.add(new GridUser(certDN, null));
136             }
137         }
138         if (list.isEmpty()) {
139             resourceAdminLog.warn("The following group returned no members: " + this);
140         }
141         return list;
142     }
143     
144     Map retrievePeopleMap(DirContext ldap) throws javax.naming.NamingException {
145         NamingEnumeration people = ldap.search("ou=People", "(description=subject=*)", null);
146         Map map = new Hashtable();
147         while (people.hasMore()) {
148             SearchResult person = (SearchResult) people.next();
149             Attributes personAtts = person.getAttributes();
150             String ldapDN = person.getName();
151             if (person.isRelative()) {
152                 ldapDN = ldapDN + ",ou=People," + ldap.getNameInNamespace();
153             }
154             
155             String certDN = (String) personAtts.get("description").get();
156             if (certDN.startsWith("subject=")) {
157                 certDN = certDN.substring(8);
158             }
159             certDN = certDN.trim();
160             map.put(ldapDN, certDN);
161         }
162         return map;
163     }
164     
165     /***
166      * Returns the name of the LDAP server used to retrieve the list of users.
167      * @return The name of the server server. i.e. "grid-vo.nikhef.nl"
168      */
169     public String getServer() {
170         return this.server;
171     }
172     
173     /***
174      * Changes the LDAP server used to retrieve the list of users.
175      * @param server The name of the server server. i.e. "grid-vo.nikhef.nl"
176      */
177     public void setServer(String server) {
178         this.server = server;
179     }
180     
181     /***
182      * The LDAP query used to retrieveGetter for property query.
183      * @return The LDAP query used. i.e. "ou=usatlas,o=atlas,dc=eu-datagrid,dc=org"
184      */
185     public String getQuery() {
186         return this.query;
187     }
188     
189     /***
190      * Changes the LDAP query used to retrieveGetter for property query.
191      * @param query The LDAP query used. i.e. "ou=usatlas,o=atlas,dc=eu-datagrid,dc=org"
192      */
193     public void setQuery(String query) {
194         this.query = query;
195     }
196     
197     public String getPersistenceFactory() {
198         return persistanceFactory.getName();
199     }
200     
201     public void setPersistence(PersistenceFactory persistanceFactory, String name) {
202         this.persistanceFactory = persistanceFactory;
203         this.name = name;
204         db = persistanceFactory.retrieveUserGroupDB(name);
205     }
206     
207     public int hashCode() {
208         return query.hashCode();
209     }
210     
211     public String toString() {
212         return "LDAPGroup: ldap://"+server+"/"+query;
213     }
214     
215     public boolean equals(Object obj) {
216         if (obj instanceof LDAPGroup) {
217             LDAPGroup group = (LDAPGroup) obj;
218             if ((server == null ? group.server == null : server.equals(group.server)) &&
219                (query == null ? group.query == null : query.equals(group.query)) && 
220                (name == null ? group.name == null : name.equals(group.name)) && 
221                (persistanceFactory == null ? group.persistanceFactory == null : persistanceFactory.getName().equals(group.persistanceFactory.getName()))) {
222                 return true;
223             }
224         }
225         return false;
226     }
227     
228 }