1
2
3
4
5
6
7 package gov.bnl.gums;
8
9 import java.net.*;
10 import java.util.*;
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13 import org.edg.security.voms.service.admin.*;
14
15 /*** A group of users residing on a VOMS vo database. This class is able to
16 * import a list of users from a VOMS server. It will store to a local
17 * medium through the UserGroupDB interface. It also manages the caching from
18 * the local database.
19 * <p>
20 * The authentication is done through the proxy, or a certificate/key/password
21 * combination. The parameters are to be set externally as system properties.
22 * The proxy can be set through "gridProxyFile" property. Other properties
23 * are "sslCertfile", "sslKey", "sslKeyPasswd" and "sslCAFiles". More documentation
24 * can be found in the documentation of the edg trustmanager
25 *
26 * @todo Should refactor with LDAPGroup, and provide a PersistanceCachedGroup
27 * since they both share local site buffering functionality
28 * @author Gabriele Carcassi
29 */
30 public class VOMSGroup implements UserGroup {
31 private Log log = LogFactory.getLog(VOMSGroup.class);
32 private Log resourceAdminLog = LogFactory.getLog(GUMS.resourceAdminLog);
33
34 private UserGroupDB db;
35 private String name;
36 private PersistenceFactory persistanceFactory;
37 private String url;
38 private String fqan;
39 private List matchFQANValues = Arrays.asList(new String[] {"ignore", "vo", "group", "exact"});
40 private String matchFQAN = "exact";
41
42 /***
43 * Holds value of property sslKey.
44 */
45 private String sslKey;
46
47 /***
48 * Holds value of property sslCertfile.
49 */
50 private String sslCertfile;
51
52 /***
53 * Holds value of property sslCAFiles.
54 */
55 private String sslCAFiles;
56
57 /***
58 * Holds value of property sslKeyPasswd.
59 */
60 private String sslKeyPasswd;
61
62 /***
63 * Holds value of property voGroup.
64 */
65 private String voGroup;
66
67 /***
68 * Holds value of property voRole.
69 */
70 private String voRole;
71
72 public java.util.List getMemberList() {
73 return db.retrieveMembers();
74 }
75
76 public String getName() {
77 return name;
78 }
79
80 public boolean isInGroup(GridUser user) {
81
82
83 if ((user.getVoFQAN() == null) && !isAcceptProxyWithoutFQAN()) {
84
85
86
87
88
89 if ((voGroup == null) && (voRole == null)) {
90 return db.isMemberInGroup(user);
91 }
92 return false;
93 }
94
95
96
97 if ((user.getVoFQAN() == null) && isAcceptProxyWithoutFQAN()) {
98 if (db.isMemberInGroup(new GridUser(user.getCertificateDN(), fqan)))
99 return true;
100 return false;
101 }
102
103
104
105
106
107 if ("exact".equals(matchFQAN)) {
108 if (!user.getVoFQAN().toString().equals(fqan))
109 return false;
110 }
111
112
113 if ("vo".equals(matchFQAN)) {
114 FQAN theFQAN = new FQAN(fqan);
115 if (!user.getVoFQAN().getVo().equals(theFQAN.getVo()))
116 return false;
117 }
118
119
120 if ("group".equals(matchFQAN)) {
121 if (!user.getVoFQAN().toString().startsWith(voGroup))
122 return false;
123 }
124
125
126
127 return db.isMemberInGroup(new GridUser(user.getCertificateDN(), fqan));
128 }
129
130 public void updateMembers() {
131 db.loadUpdatedList(retrieveMembers());
132 }
133
134 /***
135 * Returns the address of the VOMS server to contact.
136 * @return The address of the VOMS server (i.e. https://voms.myste.org:8443/edg-voms-admin/myvo/services/VOMSAdmin)
137 */
138 public String getUrl() {
139 return url;
140 }
141
142 /***
143 * Changes the address of the VOMS server to contact. The address of the server
144 * is really the address of the Web service components. If you go to that address,
145 * the AXIS servlet has to reply.
146 * @param url The address of the VOMS server (i.e. https://voms.myste.org:8443/edg-voms-admin/myvo/services/VOMSAdmin)
147 */
148 public void setUrl(String url) {
149 this.url = url;
150 }
151
152 private List retrieveMembers() {
153 Properties p = System.getProperties();
154 try {
155 setProperties();
156 log.debug("SSL properties: sslCAFiles='" + System.getProperty("sslCAFiles") +
157 "' sslCertfile='" + System.getProperty("sslCertfile") +
158 "' sslKey='" + System.getProperty("sslKey") +
159 "' sslKeyPasswd set:" + (System.getProperty("sslKeyPasswd")!= null) +"'");
160 log.info("Retrieve members: url='" + url + "' name='" + name + "' persistanceFactory='" + persistanceFactory.getName() + "'");
161 System.setProperty("axis.socketSecureFactory", "org.edg.security.trustmanager.axis.AXISSocketFactory");
162 VOMSAdminServiceLocator locator = new VOMSAdminServiceLocator();
163 URL vomsUrl = new URL(url);
164 VOMSAdmin voms = locator.getVOMSAdmin(vomsUrl);
165 org.edg.security.voms.service.User[] users = null;
166 if (voRole == null) {
167 users = voms.listMembers(getVoGroup());
168 } else {
169 users = voms.listUsersWithRole(getVoGroup(), "Role=" + getVoRole());
170 }
171 if (users.length > 0) {
172 log.trace("Retrieved " + users.length + " users. First is: '" + users[0].getDN());
173 } else {
174 log.trace("Retrieved no users.");
175 }
176 List entries = new ArrayList();
177 for (int n=0; n< users.length; n++) {
178 entries.add(new GridUser(users[n].getDN(), fqan));
179 }
180 System.setProperties(p);
181 if (entries.isEmpty()) {
182 resourceAdminLog.warn("The following group returned no members: " + this);
183 }
184 return entries;
185 } catch (Throwable e) {
186 log.error("Couldn't retrieve VOMS users: ", e);
187
188 System.setProperties(p);
189 throw new RuntimeException("Couldn't retrieve users from VOMS server: " + e.getMessage(), e);
190 }
191 }
192
193 private void setProperties() {
194 log.debug("SSL properties: sslCAFiles='" + getSslCAFiles() +"' sslCertfile='" + getSslCertfile() +"' sslKey='" + getSslKey() + "' sslKeyPasswd set:" + (getSslKeyPasswd()!= null) +"'");
195 if (getSslCAFiles() != null) {
196 System.setProperty("sslCAFiles", getSslCAFiles());
197 }
198 if (getSslCertfile() != null) {
199 System.setProperty("sslCertfile", getSslCertfile());
200 }
201 if (getSslKey() != null) {
202 System.setProperty("sslKey", getSslKey());
203 }
204 if (getSslKeyPasswd() != null) {
205 System.setProperty("sslKeyPasswd", getSslKeyPasswd());
206 }
207 }
208
209 public String getPersistenceFactory() {
210 return persistanceFactory.getName();
211 }
212
213 public void setPersistence(PersistenceFactory persistanceFactory, String name) {
214 this.persistanceFactory = persistanceFactory;
215 this.name = name;
216 db = persistanceFactory.retrieveUserGroupDB(name);
217 }
218
219 /***
220 * Returns the location of the key to be used during the connection.
221 * @return The location of the key (i.e. /etc/grid-security/hostkey.pem)
222 */
223 public String getSslKey() {
224 return this.sslKey;
225 }
226
227 /***
228 * Changes the location of the private key used to connect to the VOMS server.
229 * @param sslKey The location of the key (i.e. /etc/grid-security/hostkey.pem)
230 */
231 public void setSslKey(String sslKey) {
232 this.sslKey = sslKey;
233 }
234
235 /***
236 * Returns the location of the certificated used to connect to the VOMS server.
237 * @return The location of the certificate (i.e. /etc/grid-security/hostcert.pem)
238 */
239 public String getSslCertfile() {
240 return this.sslCertfile;
241 }
242
243 /***
244 * Changes the location of the certificated used to connect to the VOMS server.
245 * @param sslCertfile The location of the certificate (i.e. /etc/grid-security/hostcert.pem)
246 */
247 public void setSslCertfile(String sslCertfile) {
248 this.sslCertfile = sslCertfile;
249 }
250
251 /***
252 * Returns the location of the Certificate Authority certificates used to connect to the VOMS server.
253 * @return The location of the CA certificates (i.e. /etc/grid-security/certificates/*.0)
254 */
255 public String getSslCAFiles() {
256 return this.sslCAFiles;
257 }
258
259 /***
260 * Changes the location of the Certificate Authority certificates used to connect to the VOMS server.
261 * @param sslCAFiles The location of the CA certificates (i.e. /etc/grid-security/certificates/*.0)
262 */
263 public void setSslCAFiles(String sslCAFiles) {
264 this.sslCAFiles = sslCAFiles;
265 }
266
267 /***
268 * Returns the private key password used to connect to the VOMS server.
269 * @return The password for the private key
270 */
271 public String getSslKeyPasswd() {
272 return this.sslKeyPasswd;
273 }
274
275 /***
276 * Changes the private key password used to connect to the VOMS server.
277 * @param sslKeyPasswd The password for the private key
278 */
279 public void setSslKeyPasswd(String sslKeyPasswd) {
280 this.sslKeyPasswd = sslKeyPasswd;
281 }
282
283
284 public String toString() {
285 return "VOMSGroup: "+url+" - voGroup='" + getVoGroup() + "' - voRole='" + getVoRole() + "' - sslCAFiles='" + getSslCAFiles() +"' sslCertfile='" + getSslCertfile() +"' sslKey='" + getSslKey() + "' sslKeyPasswd=" + ((getSslKeyPasswd()!= null) ? "[set]" : "[not set]");
286 }
287
288 /***
289 * Returns the group to be retrieved from the VO.
290 * @return The group in the VOMS (i.e. /atlas/usatlas)
291 */
292 public String getVoGroup() {
293 return this.voGroup;
294 }
295
296 /***
297 * Changes the group to be retrieved from the VO.
298 * @param voGroup The group in the VOMS (i.e. /atlas/usatlas)
299 */
300 public void setVoGroup(String voGroup) {
301 this.voGroup = voGroup;
302 prepareFQAN();
303 }
304
305 /***
306 * Changes the role to be retrieved within the VO group.
307 * @return The role name in the VOMS server (i.e. myrole), or null for no role
308 */
309 public String getVoRole() {
310 return this.voRole;
311 }
312
313 /***
314 * Changes the role to be retrieved within the VO group.
315 * @param voRole The role name in the VOMS server (i.e. myrole), or null for no role
316 */
317 public void setVoRole(String voRole) {
318 this.voRole = voRole;
319 prepareFQAN();
320 }
321
322 private void prepareFQAN() {
323 if (voGroup == null) {
324 fqan = null;
325 } else {
326 if (voRole == null) {
327 fqan = voGroup;
328 } else {
329 fqan = voGroup + "/Role=" + voRole;
330 }
331 }
332 }
333
334 /***
335 * Tells whether the FQAN should be used to match the proxy or not. If set to false,
336 * the FQAN has to be present (i.e. won't accept non VOMS proxy) and has to match
337 * the one defined by the group. If set to true, the FQAN is not looked at, making
338 * all proxies (non VOMS and VOMS proxy with different FQAN) match as long as the
339 * DN matches. Setting true makes the behaviour similar to the one of the
340 * grid-mapfile.
341 * @return False if FQAN is used during the match
342 * @deprecated As of GUMS 1.1, use matchFQAN and acceptProxyWithoutFQAN
343 */
344 public boolean isIgnoreFQAN() {
345 return "ignore".equals(matchFQAN);
346 }
347
348 /***
349 * Changes the way FQAN is used to match.
350 * @param ignoreFQAN False if FQAN is used during the matchNew value of property ignoreFQAN.
351 * @deprecated As of GUMS 1.1, use matchFQAN and acceptProxyWithoutFQAN
352 */
353 public void setIgnoreFQAN(boolean ignoreFQAN) {
354 resourceAdminLog.warn("The attribute \"ignoreFQAN\" for VOMSGroup is deprecated: use matchFQAN instead. DO NOT MIX ignoreFQAN and matchFQAN.");
355 if (ignoreFQAN) {
356 matchFQAN = "ignore";
357 acceptProxyWithoutFQAN = true;
358 } else {
359 matchFQAN = "exact";
360 acceptProxyWithoutFQAN = false;
361 }
362 }
363
364 /***
365 * The scheme according to which the FQAN will be matched.
366 * <p>
367 * Possible values are:
368 * <ul>
369 * <li>exact (default) - the FQAN in the proxy has to be the same as
370 * what the VOMSGroup is set to. </li>
371 * <li>group - the FQAN in the proxy has to be the same group, or any
372 * subgroup; role is ignored.</li>
373 * <li>vo - the FQAN in the proxy has to be of the same vo.</li>
374 * <li>ignore - the FQAN in the proxy is completely ignored.</li>
375 * </ul>
376 * @return One of the following: "ignore", "vo", "group" or "exact".
377 */
378 public String getMatchFQAN() {
379
380 return this.matchFQAN;
381 }
382
383 /***
384 * Changes the scheme according to which the FQAN will be matched. See
385 * getMatchFQAN for more details.
386 * @param matchFQAN One of the following: "ignore", "vo", "group" or "exact".
387 */
388 public void setMatchFQAN(String matchFQAN) {
389 if (!matchFQANValues.contains(matchFQAN)) {
390 throw new IllegalArgumentException("The accepted values for matchFQAN in VOMSGroup are: " + matchFQANValues);
391 }
392
393 this.matchFQAN = matchFQAN;
394 }
395
396 /***
397 * Holds value of property acceptProxyWithoutFQAN.
398 */
399 private boolean acceptProxyWithoutFQAN;
400
401 /***
402 * True if non-VOMS will be accepted. If true, all non-VOMS proxies with a matchin
403 * DN will be matched. VOMS proxies won't be affected by the use of this property.
404 * @return True if group will accept non-VOMS proxies
405 */
406 public boolean isAcceptProxyWithoutFQAN() {
407
408 return this.acceptProxyWithoutFQAN;
409 }
410
411 /***
412 * Changes the way non-VOMS proxies are handled.
413 * @param acceptProxyWithoutFQAN True if group will accept non-VOMS proxies
414 */
415 public void setAcceptProxyWithoutFQAN(boolean acceptProxyWithoutFQAN) {
416
417 this.acceptProxyWithoutFQAN = acceptProxyWithoutFQAN;
418 }
419
420 }