View Javadoc

1   /*
2    * CoreLogic.java
3    *
4    * Created on May 24, 2004, 3:17 PM
5    */
6   
7   package gov.bnl.gums;
8   
9   import gov.bnl.gums.account.*;
10  import gov.bnl.gums.configuration.Configuration;
11  import gov.bnl.gums.groupToAccount.GroupToAccountMapping;
12  import gov.bnl.gums.hostToGroup.HostToGroupMapping;
13  import gov.bnl.gums.userGroup.UserGroup;
14  import gov.bnl.gums.userGroup.VOMSUserGroup;
15  
16  import java.util.*;
17  
18  import org.apache.log4j.Logger;
19  
20  /** 
21   * The main interface of the core logic for GUMS, allows to update the
22   * groups, generate the gridMapfiles and to map a single user.
23   *
24   * @author Gabriele Carcassi, Jay Packard
25   */
26  public class CoreLogic {
27      private Logger log = Logger.getLogger(CoreLogic.class); // only use this log for particularly tricky aspects of this class - otherwise log within lower level classes
28      private Logger gumsAdminLog = Logger.getLogger(GUMS.gumsAdminLogName);
29      GUMS gums;
30      
31      /**
32       * Creates a Resource Manager for a particular instance of the GUMS server.
33       * 
34       * @param gums
35       */
36      public CoreLogic(GUMS gums) {
37      	this.gums = gums;
38      }
39      
40      
41      /**
42       * @param hostname
43       * @return
44       */
45      public String generateOsgUserVoMap(String hostname) throws Exception {
46          Configuration conf = gums.getConfiguration();
47          StringBuffer osgMapBuffer = new StringBuffer("");
48          HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
49          if (host2GroupMapper == null) {
50          	String message = "Cannot generate osg user VO map for host '" + hostname + "' - it is not defined in any host to group mapping.";
51              gumsAdminLog.warn(message);
52          	throw new RuntimeException(message);
53          }
54          
55          // Create header
56          osgMapBuffer.append("#User-VO map\n");
57          osgMapBuffer.append("# #comment line, format of each regular line line: account VO\n");
58          osgMapBuffer.append("# Next 2 lines with VO names, same order, all lowercase, with case (lines starting with #voi, #VOc)\n");
59          String voi = "#voi";
60          String voc = "#VOc";
61          Iterator iter = host2GroupMapper.getGroupToAccountMappings().iterator();
62          while (iter.hasNext()) {
63              GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
64              Collection userGroups = gMap.getUserGroups();
65              Iterator userGroupIt = userGroups.iterator();
66              while (userGroupIt.hasNext()) {
67              	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
68  	            if (userGroup.getMemberList().size()!=0 && !gMap.getAccountingVoSubgroup().equals("") && !gMap.getAccountingVo().equals("")) {
69  	                voi = voi + " " + gMap.getAccountingVoSubgroup();
70  	                voc = voc + " " + gMap.getAccountingVo();
71  	            }
72              }
73          }
74          osgMapBuffer.append(voi);
75          osgMapBuffer.append("\n");
76          osgMapBuffer.append(voc);
77          osgMapBuffer.append("\n");
78          
79          // Loop through group to account mappings
80          List accountsInMap = new ArrayList();
81          int unknownCount = 1;
82          iter = host2GroupMapper.getGroupToAccountMappings().iterator();
83          while (iter.hasNext()) {
84              GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
85              if (!gMap.getAccountingVoSubgroup().equals("") && !gMap.getAccountingVo().equals("")) {
86  	            Collection userGroups = gMap.getUserGroups();
87              	Collection accountMappers = gMap.getAccountMappers();
88  	            Iterator userGroupIt = userGroups.iterator();
89  	            while (userGroupIt.hasNext()) {
90  	            	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
91  		            List members = userGroup.getMemberList();
92  		            members = new ArrayList(members);
93  		            osgMapBuffer.append("#---- accounts for vo: " + userGroup.getName() + " ----#\n");          
94  		            Collections.sort(members, retrieveUserComparatorByDN());
95  		            Iterator memberIter = members.iterator();
96  		            while (memberIter.hasNext()) {
97  		                GridUser user = (GridUser) memberIter.next();
98  		                if (gums.isUserBanned(user))
99  		                	continue;
100 	                    Iterator accountMapperIt = accountMappers.iterator();
101 	                    while (accountMapperIt.hasNext()) {
102 	                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMapperIt.next() );
103 			                String account = accountMapper.mapUser(user, false);
104 			                if ((account != null) && !accountsInMap.contains(account)) {
105 			                	osgMapBuffer.append(account);
106 			                	osgMapBuffer.append(' ');
107 			                	osgMapBuffer.append(gMap.getAccountingVoSubgroup());
108 			                	osgMapBuffer.append("\n");
109 			                    accountsInMap.add(account);
110 			                }
111 	                    }
112 		            }
113 	            }
114             }
115         }
116         
117         String finalOsgMap = osgMapBuffer.toString();
118         return finalOsgMap;
119     }
120     
121 
122     /**
123      * Generates a fqan to account mapping for a given host and prints it to out.
124      * 
125      * @param hostname
126      * @return
127      */
128     public String generateFqanMapfile(String hostname) throws Exception {
129         String mapfile;
130         mapfile = generateFqanMapfileImpl(hostname);
131         return mapfile;
132     }    
133     
134     /**
135      * Generates a grid mapfile for a given host and prints it to out.
136      * 
137      * @param hostname
138      * @param includeFQAN
139      * @return
140      */
141     public String generateGridMapfile(String hostname, boolean createNewMappings, boolean includeFQAN, boolean includeEmail) throws Exception {
142         String mapfile;
143         mapfile = generateGridMapfileImpl(hostname, createNewMappings, includeFQAN, includeEmail);
144         return mapfile;
145     }
146     
147     /**
148      * Maps a user to a local account for a given host to a grid identity.
149      * 
150      * @param hostname
151      * @param user
152      * @return
153      */
154     public String map(String hostname, GridUser user, boolean checkBannedList) throws Exception {
155         if (checkBannedList && gums.isUserBanned(user))
156         	return null;
157         String account = mapImpl(hostname, user);
158         return account;
159     }
160     
161     /**
162      * Map a local account to a list of grid identity
163      * 
164      * @param accountName
165      * @return
166      */
167     public String mapAccount(String accountName) throws Exception {
168     	TreeSet dns = new TreeSet();
169         Configuration conf = gums.getConfiguration();
170         Iterator g2AMappingsIt = conf.getGroupToAccountMappings().values().iterator();
171         while (g2AMappingsIt.hasNext()) {
172             GroupToAccountMapping g2AMapping = (GroupToAccountMapping) g2AMappingsIt.next();
173             Collection userGroups = g2AMapping.getUserGroups();
174             Iterator userGroupsIt = userGroups.iterator();
175             while (userGroupsIt.hasNext()) {
176             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupsIt.next() );
177             	List users = userGroup.getMemberList();
178             	Iterator usersIt = users.iterator();
179             	while (usersIt.hasNext()) {
180             		GridUser user = (GridUser)usersIt.next();
181             		if (gums.isUserBanned(user))
182                     	continue;
183                 	Collection accountMappers = g2AMapping.getAccountMappers();
184                     Iterator accountMappersIt = accountMappers.iterator();
185                     while (accountMappersIt.hasNext()) {
186                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
187 			if (accountName.equals(accountMapper.mapUser(user, false)) && !dns.contains(user.getCertificateDN()))
188                         	dns.add(user.getCertificateDN());
189                     }            		
190             	}
191             }
192         }
193         
194         if (dns.size()==0) {
195             gumsAdminLog.warn("Cannot map account '" + accountName + "' to any DN.");
196         }
197 
198         StringBuffer output = new StringBuffer();
199         Iterator it = dns.iterator();
200         while(it.hasNext()) {
201         	output.append( (String)it.next() );
202         	output.append("\n");
203         }
204 
205 		gumsAdminLog.info("Mapped the account '" + accountName + "' to '" + output.toString() + "'");
206         return output.toString();
207     }
208     
209     /**
210      * Scans the configuration and calls updateMembers() on all the groups,
211      * updating the local database.
212      */
213     public void updateGroups() throws Exception {
214         updateGroupsImpl();
215     }
216     
217     /**
218      * Scans the configuration and calls updateMembers() on all the banned groups,
219      * updating the local database.
220      */
221     public void updateBannedGroups() throws Exception {
222         updateBannedGroupsImpl();
223     }
224     
225     /**
226      * @param hostname
227      * @return
228      */
229     private String generateFqanMapfile(HostToGroupMapping hToGMapping) {   
230        	Configuration conf = hToGMapping.getConfiguration();
231         Iterator iter = hToGMapping.getGroupToAccountMappings().iterator();
232         TreeSet usersInMap = new TreeSet();
233         
234         StringBuffer fqanMapfileBuffer = new StringBuffer("");
235         while (iter.hasNext()) {
236             GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
237             Collection userGroups = gMap.getUserGroups();
238             Iterator userGroupIt = userGroups.iterator();
239             while (userGroupIt.hasNext()) {
240             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
241             	if (userGroup instanceof VOMSUserGroup) {
242             		VOMSUserGroup vomsUserGroup = (VOMSUserGroup)userGroup;
243             		Collection accountMappers = gMap.getAccountMappers();
244                     Iterator accountMapperIt = accountMappers.iterator();
245                     while (accountMapperIt.hasNext()) {
246                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMapperIt.next() );
247                     	if (accountMapper instanceof GroupAccountMapper || accountMapper instanceof AccountPoolMapper) {
248 	                		String fqan = vomsUserGroup.getVoGroup() + (vomsUserGroup.getRole().equals("") ? "" : "/Role=" + vomsUserGroup.getRole());
249                         	String account = null;
250 	                       	if (accountMapper instanceof GroupAccountMapper) {
251 	                    		GroupAccountMapper groupPoolMapper = (GroupAccountMapper)accountMapper;
252 	                    		account = groupPoolMapper.getAccountName();
253 	                    	}
254 	                    	else if (accountMapper instanceof AccountPoolMapper){
255 	                    		AccountPoolMapper accountPoolMapper = (AccountPoolMapper)accountMapper;
256 	                    		account = accountPoolMapper.getAssignments();
257 	                    		if (account==null || account.length()==0)
258 	                    			account = "null";
259 	                    	}
260 	                       	if (account != null) {
261 	                       		fqanMapfileBuffer.append('"');
262 	                       		fqanMapfileBuffer.append( fqan );
263 	                       		fqanMapfileBuffer.append('"');
264 	                       		fqanMapfileBuffer.append(' ');
265 	                       		fqanMapfileBuffer.append( account );
266 	                       		fqanMapfileBuffer.append("\n");
267 	                       		break;
268 	                       	}
269                     	}
270                     }
271             	}
272             }
273         }
274         
275         return fqanMapfileBuffer.toString();
276     }    
277     
278     private String generateGridMapfile(HostToGroupMapping hToGMapping, boolean createNewMappings, boolean includeFQAN, boolean includeEmail) throws Exception {
279     	Configuration conf = hToGMapping.getConfiguration();
280         Iterator iter = hToGMapping.getGroupToAccountMappings().iterator();
281         HashSet usersInMap = new HashSet();
282         
283         StringBuffer gridMapfileBuffer = new StringBuffer("");
284         while (iter.hasNext()) {
285             GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
286             Collection userGroups = gMap.getUserGroups();
287             Iterator userGroupIt = userGroups.iterator();
288             while (userGroupIt.hasNext()) {
289             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
290 	            List members = userGroup.getMemberList();
291 	            members = new ArrayList(members);
292 	            Collections.sort(members, retrieveUserComparatorByDN());
293 	            gridMapfileBuffer.append("#---- members of vo: " + userGroup.getName() + " ----#\n");
294 	            Iterator memberIter = members.iterator();
295 	            if (includeFQAN) {
296 		            while (memberIter.hasNext()) {
297 		                GridUser user = (GridUser) memberIter.next();
298 		                if (gums.isUserBanned(user))
299 	                    	continue;
300 	                    	String fqan = user.getVoFQAN()!=null?user.getVoFQAN().toString():"";
301 	                    	String email = user.getEmail()!=null?user.getEmail().toString():"";
302 		                if (!usersInMap.contains(user.getCertificateDN() + fqan) ) {
303 		                    Collection accountMappers = gMap.getAccountMappers();
304 		                    Iterator accountMappersIt = accountMappers.iterator();
305 		                    while (accountMappersIt.hasNext()) {
306 		                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
307 			                	String account = accountMapper.mapUser(user, true);
308 			                	if (account != null) {
309 			                        gridMapfileBuffer.append('"');
310 			                        gridMapfileBuffer.append( user.getCertificateDN() );
311 			                        gridMapfileBuffer.append('"' );
312 			                        gridMapfileBuffer.append(" \"");
313 			                        gridMapfileBuffer.append( fqan );
314 			                        gridMapfileBuffer.append('"');         	
315 			                        gridMapfileBuffer.append(' ');
316 			                        gridMapfileBuffer.append( account );
317 			                        if (includeEmail) {
318 				                        gridMapfileBuffer.append(' ');
319 				                        gridMapfileBuffer.append( email );
320 			                        }
321 			                        gridMapfileBuffer.append("\n");
322 		                        	usersInMap.add( user.getCertificateDN() + fqan );
323 		                        	break;
324 			                    } else {
325 			                    	gumsAdminLog.debug("User " + user + " from group " + gMap.getUserGroups() + " can't be mapped.");
326 			                    }
327 		                    }
328 		            	}
329 		            }
330 	            }
331 	            else {
332 		            while (memberIter.hasNext()) {
333 		                GridUser user = (GridUser) memberIter.next();
334 		                if (gums.isUserBanned(user))
335 	                    	continue;
336 		                String email = user.getEmail()!=null?user.getEmail().toString():"";
337 		                if (!usersInMap.contains(user.getCertificateDN()) && userGroup.isInGroup(new GridUser(user.getCertificateDN(), null))) {
338 		                	Collection accountMappers = gMap.getAccountMappers();
339 		                    Iterator accountMappersIt = accountMappers.iterator();
340 		                    while (accountMappersIt.hasNext()) {
341 		                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
342 			                	String account = accountMapper.mapUser(user, true);
343 			                    if (account != null) {
344 			                        gridMapfileBuffer.append('"');
345 			                        gridMapfileBuffer.append( user.getCertificateDN() );
346 			                        gridMapfileBuffer.append('"' );
347 			                        gridMapfileBuffer.append(' ');
348 			                        gridMapfileBuffer.append( account );
349 			                        if (includeEmail && email!=null) {
350 				                        gridMapfileBuffer.append(' ');
351 				                        gridMapfileBuffer.append( email );
352 			                        }
353 			                        gridMapfileBuffer.append("\n");
354 		                        	usersInMap.add(user.getCertificateDN());
355 		                        	break;
356 			                    } else {
357 			                    	gumsAdminLog.debug("User " + user + " from group " + gMap.getUserGroups() + " can't be mapped.");
358 			                    }
359 		                    }
360 		            	}
361 		            }	            	
362 	            }
363             }
364         }
365 
366         String finalGridmapfile = gridMapfileBuffer.toString();
367         return finalGridmapfile;
368     }
369  
370     private String generateFqanMapfileImpl(String hostname) throws Exception {
371         Configuration conf = gums.getConfiguration();
372         HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
373         if (host2GroupMapper == null) {
374         	String message = "Cannot generate FQAN mapfile for host '" + hostname + "' - it is not defined in any host to group mapping.";
375             gumsAdminLog.warn(message);
376         	throw new RuntimeException(message);
377         }
378         String mapfile = generateFqanMapfile(host2GroupMapper);
379         return mapfile;
380     }
381     
382     private String generateGridMapfileImpl(String hostname, boolean createNewMappings, boolean includeFqan, boolean includeEmail) throws Exception {
383     	Configuration conf = gums.getConfiguration();
384         HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
385         if (host2GroupMapper == null) {
386         	String message = "Cannot generate grid mapfile for host '" + hostname + "' - it is not defined in any host to group mapping.";
387             gumsAdminLog.warn(message);
388         	throw new RuntimeException(message);
389         }
390         String mapfile = generateGridMapfile(host2GroupMapper, createNewMappings, includeFqan, includeEmail);
391         return mapfile;
392     }
393     
394     private HostToGroupMapping hostToGroupMapping(Configuration conf, String hostname) {
395     	Collection hostToGroupMappers = conf.getHostToGroupMappings();
396     	Iterator it = hostToGroupMappers.iterator();
397         while (it.hasNext()) {
398             HostToGroupMapping hostToGroupMapper = (HostToGroupMapping) it.next();
399             if (hostToGroupMapper.isInGroup(hostname)) {
400                 return hostToGroupMapper;
401             }
402         }
403         return null;
404     }
405 
406     private String mapImpl(String hostname, GridUser user) throws Exception {
407         Configuration conf = gums.getConfiguration();
408         HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
409         if (host2GroupMapper == null) {
410         	String message = "Cannot map user for host '" + hostname + "' - it is not defined in any host to group mapping.";
411             gumsAdminLog.warn(message);
412         	throw new RuntimeException(message);
413         }
414         Iterator g2AMappingsIt = host2GroupMapper.getGroupToAccountMappings().iterator();
415         while (g2AMappingsIt.hasNext()) {
416             GroupToAccountMapping g2AMapping = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)g2AMappingsIt.next() );
417             Collection userGroups = g2AMapping.getUserGroups();
418             Iterator userGroupsIt = userGroups.iterator();
419             while (userGroupsIt.hasNext()) {
420             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupsIt.next() );
421                 if (userGroup.isInGroup(user)) {
422                 	Collection accountMappers = g2AMapping.getAccountMappers();
423                     Iterator accountMappersIt = accountMappers.iterator();
424                     while (accountMappersIt.hasNext()) {
425                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
426                         String localUser = accountMapper.mapUser(user, true);
427                         if (localUser != null)
428                             return localUser;
429                     }
430                 }
431             }
432         }
433         return null;
434     }
435 
436     private Comparator retrieveUserComparatorByDN() {
437         return new Comparator() {
438             public int compare(Object o1, Object o2) {
439                 GridUser user1 = (GridUser) o1;
440                 GridUser user2 = (GridUser) o2;
441                 return user1.compareDn(user2);
442             }
443         };
444     }
445     
446     private void updateGroupsImpl() throws Exception {
447         Collection groups = gums.getConfiguration().getUserGroups().values();
448         gumsAdminLog.info("Updating user group users for all " + groups.size() + " user groups");
449         StringBuffer failedGroups = null;
450         Iterator iter = groups.iterator();
451         while (iter.hasNext()) {
452             UserGroup group = (UserGroup) iter.next();
453             if (!gums.getConfiguration().getBannedUserGroupList().contains(group)) {
454             	// Banned user groups updated in another function
455 	            try {
456 	                group.updateMembers();
457 	                gumsAdminLog.info("User group update for " + group.getName() + " (" + group.getMemberList().size() + " users).");
458 	            } catch (Exception e) {
459 	                gumsAdminLog.warn("User group update for " + group.getName() + " failed: " + e.getMessage());
460 	            	if (failedGroups == null)
461 	            		failedGroups = new StringBuffer("Some user groups weren't updated correctly:\n");
462 	            	failedGroups.append( group.getName() + " - " + e.getMessage() + "\n" );
463 	            }
464             }
465         }
466         if (failedGroups == null) {
467         	gumsAdminLog.info("Finished updating users for all user groups");
468         }
469         else {
470         	gumsAdminLog.warn("Some user groups weren't updated correctly");
471             throw new RuntimeException(failedGroups.toString());
472         }
473     }
474     
475     private void updateBannedGroupsImpl() throws Exception {
476         Collection groups = gums.getConfiguration().getBannedUserGroupList();
477         if (groups.size()>0) {
478 	        gumsAdminLog.info("Updating user group users for all " + groups.size() + " banned user groups");
479 	        StringBuffer failedGroups = null;
480 	        Iterator iter = groups.iterator();
481 	        while (iter.hasNext()) {
482 	            UserGroup group = (UserGroup) iter.next();
483 	            try {
484 	                group.updateMembers();
485 	                gumsAdminLog.info("User group update for " + group.getName() + " (" + group.getMemberList().size() + " users).");
486 	            } catch (Exception e) {
487 	                gumsAdminLog.warn("User group update for " + group.getName() + " failed: " + e.getMessage());
488 	            	if (failedGroups == null)
489 	            		failedGroups = new StringBuffer("Some banned user groups weren't updated correctly:\n");
490 	            	failedGroups.append( group.getName() + " - " + e.getMessage() + "\n" );
491 	            }
492 	        }
493 	        if (failedGroups == null) {
494 	        	gumsAdminLog.info("Finished updating banned users for all user groups");
495 	        }
496 	        else {
497 	        	gumsAdminLog.warn("Some banned user groups weren't updated correctly");
498 	            throw new RuntimeException(failedGroups.toString());
499 	        }
500         }
501     }    
502 }