1 56 package org.opencrx.kernel.layer.model; 57 58 import java.util.HashMap ; 59 import java.util.HashSet ; 60 import java.util.Iterator ; 61 import java.util.List ; 62 import java.util.Map ; 63 import java.util.Set ; 64 65 import org.opencrx.kernel.generic.SecurityKeys; 66 import org.openmdx.application.log.AppLog; 67 import org.openmdx.base.exception.ServiceException; 68 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSelectors; 69 import org.openmdx.compatibility.base.dataprovider.cci.AttributeSpecifier; 70 import org.openmdx.compatibility.base.dataprovider.cci.DataproviderObject_1_0; 71 import org.openmdx.compatibility.base.dataprovider.cci.Orders; 72 import org.openmdx.compatibility.base.dataprovider.cci.RequestCollection; 73 import org.openmdx.compatibility.base.dataprovider.cci.SystemAttributes; 74 import org.openmdx.compatibility.base.naming.Path; 75 import org.openmdx.compatibility.base.query.FilterOperators; 76 import org.openmdx.compatibility.base.query.FilterProperty; 77 import org.openmdx.compatibility.base.query.Quantors; 78 import org.openmdx.kernel.exception.BasicException; 79 80 83 public class SecurityContext { 84 85 public SecurityContext( 87 AccessControl_1 plugin, 88 Path realmIdentity 89 ) { 90 this.plugin = plugin; 91 this.realmIdentity = realmIdentity; 92 this.isActive = true; 93 if(System.getProperty(SecurityKeys.ENABLE_SECURITY_PROPERTY) != null) { 94 this.isActive = "true".equals(System.getProperty(SecurityKeys.ENABLE_SECURITY_PROPERTY)); 95 } 96 if(!this.isActive) { 97 System.out.println("WARNING: AccessControl_1 is not active. Activate with system property " + SecurityKeys.ENABLE_SECURITY_PROPERTY + "=true. Default is true."); 98 } 99 } 100 101 private Set getAllSubgroups( 103 Path groupIdentity 104 ) throws ServiceException { 105 Set subgroups = new HashSet (); 106 subgroups.add( 107 this.plugin.getQualifiedPrincipalName(groupIdentity) 108 ); 109 for(Iterator i = this.groups.values().iterator(); i.hasNext(); ) { 110 DataproviderObject_1_0 group = (DataproviderObject_1_0)i.next(); 111 if(group.values("isMemberOf").contains(groupIdentity)) { 112 subgroups.addAll( 113 this.getAllSubgroups(group.path()) 114 ); 115 subgroups.add( 116 this.plugin.getQualifiedPrincipalName(group.path()) 117 ); 118 } 119 } 120 return subgroups; 121 } 122 123 private Set getAllSupergroups( 125 Path groupIdentity 126 ) throws ServiceException { 127 Set supergroups = new HashSet (); 128 DataproviderObject_1_0 group = (DataproviderObject_1_0)this.groups.get(groupIdentity); 129 if(group == null) { 130 AppLog.error("Can not find group in group list", "group=" + groupIdentity + "; groups=" + this.groups); 131 } 132 else { 133 supergroups.add( 134 this.plugin.getQualifiedPrincipalName(groupIdentity) 135 ); 136 for(Iterator i = group.values("isMemberOf").iterator(); i.hasNext(); ) { 137 supergroups.addAll( 138 this.getAllSupergroups((Path)i.next()) 139 ); 140 } 141 } 142 return supergroups; 143 } 144 145 149 private void assertPrincipals( 150 String principalName, 151 boolean checkGroups 152 ) throws ServiceException { 153 RequestCollection delegation = this.plugin.getRunAsRootDelegation(); 154 DataproviderObject_1_0 principal = null; 155 try { 156 principal = delegation.addGetRequest( 157 this.realmIdentity.getDescendant(new String []{"principal", principalName}) 158 ); 159 this.principals.put( 160 principal.path().getBase(), 161 principal 162 ); 163 } 164 catch(ServiceException e) { 165 this.principals.remove(principalName); 167 } 168 AppLog.info("principal cache size", new Integer (this.principals.size())); 169 170 if(checkGroups) { 171 List principalGroups = delegation.addFindRequest( 173 this.realmIdentity.getChild("principal"), 174 new FilterProperty[]{ 175 new FilterProperty( 176 Quantors.THERE_EXISTS, 177 SystemAttributes.OBJECT_CLASS, 178 FilterOperators.IS_IN, 179 new String []{"org:opencrx:security:realm1:PrincipalGroup"} 180 ) 181 }, 182 AttributeSelectors.ALL_ATTRIBUTES, 183 null, 184 0, 185 Integer.MAX_VALUE, 186 Orders.ASCENDING 187 ); 188 this.groups = new HashMap (); 189 for( 190 Iterator i = principalGroups.iterator(); 191 i.hasNext(); 192 ) { 193 DataproviderObject_1_0 principalGroup = (DataproviderObject_1_0)i.next(); 194 this.groups.put( 195 principalGroup.path(), 196 principalGroup 197 ); 198 } 199 200 this.subgroups = new HashMap (); 202 this.supergroups = new HashMap (); 203 for(Iterator i = this.groups.keySet().iterator(); i.hasNext(); ) { 204 Path groupIdentity = (Path)i.next(); 205 this.subgroups.put( 206 this.plugin.getQualifiedPrincipalName(groupIdentity), 207 this.getAllSubgroups(groupIdentity) 208 ); 209 this.supergroups.put( 210 this.plugin.getQualifiedPrincipalName(groupIdentity), 211 this.getAllSupergroups(groupIdentity) 212 ); 213 } 214 } 215 } 216 217 protected DataproviderObject_1_0 getPrincipal( 219 String principalName 220 ) throws ServiceException { 221 222 DataproviderObject_1_0 principal = this.principals == null 223 ? null 224 : (DataproviderObject_1_0)this.principals.get(principalName); 225 226 if( 228 (principal == null) || 229 (System.currentTimeMillis() > this.securityRealmCheckAt) 230 ) { 231 RequestCollection delegation = this.plugin.getRunAsRootDelegation(); 232 DataproviderObject_1_0 realm = delegation.addGetRequest( 233 this.realmIdentity, 234 AttributeSelectors.ALL_ATTRIBUTES, 235 new AttributeSpecifier[]{} 236 ); 237 String securityRealmModifiedAt = (String )realm.values(SystemAttributes.MODIFIED_AT).get(0); 238 this.assertPrincipals( 239 principalName, 240 securityRealmModifiedAt.compareTo(this.securityRealmModifiedAt) != 0 241 ); 242 this.securityRealmModifiedAt = securityRealmModifiedAt; 243 this.securityRealmCheckAt = System.currentTimeMillis() + SECURITY_REAL_CHECK_RATE; 244 } 245 246 if(principal == null) { 247 principal = (DataproviderObject_1_0)this.principals.get(principalName); 248 if(principal == null) { 249 AppLog.warning("principal not found", principalName); 250 throw new ServiceException( 251 BasicException.Code.DEFAULT_DOMAIN, 252 BasicException.Code.NOT_FOUND, 253 new BasicException.Parameter[]{ 254 new BasicException.Parameter("realm", this.realmIdentity), 255 new BasicException.Parameter("principal", principalName) 256 }, 257 "principal not found" 258 ); 259 } 260 } 261 return principal; 262 } 263 264 protected DataproviderObject_1_0 getUserHome( 266 Path principalIdentity 267 ) throws ServiceException { 268 String providerName = principalIdentity.get(2); 269 String segmentName = principalIdentity.get(principalIdentity.size()-3); 270 RequestCollection delegation = this.plugin.getRunAsRootDelegation(); 271 return delegation.addGetRequest( 272 new Path("xri:@openmdx:org.opencrx.kernel.home1/provider/" + providerName + "/segment/" + segmentName + "/userHome/" + principalIdentity.getBase()), 273 AttributeSelectors.ALL_ATTRIBUTES, 274 new AttributeSpecifier[]{} 275 ); 276 } 277 278 protected DataproviderObject_1_0 getPrimaryGroup( 280 DataproviderObject_1_0 principal 281 ) throws ServiceException { 282 try { 283 DataproviderObject_1_0 userHome = this.getUserHome(principal.path()); 284 Path userGroupIdentity = (Path)userHome.values("primaryGroup").get(0); 285 return userGroupIdentity == null 286 ? this.getPrincipal(principal.path().getBase() + "." + SecurityKeys.USER_SUFFIX) 287 : this.getPrincipal(userGroupIdentity.getBase()); 288 } 289 catch(Exception e) { 292 return this.getPrincipal(principal.path().getBase() + "." + SecurityKeys.USER_SUFFIX); 293 } 294 } 295 296 302 protected DataproviderObject_1_0 getGroup( 303 DataproviderObject_1_0 principal 304 ) throws ServiceException { 305 DataproviderObject_1_0 group = (DataproviderObject_1_0)this.groupMapping.get(principal.path()); 306 if(group == null) { 307 RequestCollection delegation = this.plugin.getRunAsRootDelegation(); 308 List owningGroups = delegation.addFindRequest( 309 this.realmIdentity.getChild("principal"), 310 new FilterProperty[]{ 311 new FilterProperty( 312 Quantors.THERE_EXISTS, 313 "subject", 314 FilterOperators.IS_IN, 315 new Object []{ 316 principal.values("subject").get(0) 317 } 318 ), 319 new FilterProperty( 320 Quantors.THERE_EXISTS, 321 SystemAttributes.OBJECT_CLASS, 322 FilterOperators.IS_IN, 323 new String []{ 324 "org:opencrx:security:realm1:User" 325 } 326 ) 327 }, 328 AttributeSelectors.ALL_ATTRIBUTES, 329 null, 330 0, 331 Integer.MAX_VALUE, 332 Orders.ASCENDING 333 ); 334 if(owningGroups.size() == 0) { 335 throw new ServiceException( 336 BasicException.Code.DEFAULT_DOMAIN, 337 BasicException.Code.NOT_FOUND, 338 new BasicException.Parameter[]{ 339 new BasicException.Parameter("principal", principal.path()) 340 }, 341 "Undefined user for principal" 342 ); 343 } 344 group = (DataproviderObject_1_0)owningGroups.iterator().next(); 345 this.groupMapping.put( 346 principal.path(), 347 group 348 ); 349 } 350 return group; 351 } 352 353 357 protected Set getSubgroups( 358 String qualifiedPrincipalName 359 ) throws ServiceException { 360 Set subgroups = (Set )this.subgroups.get(qualifiedPrincipalName); 361 return subgroups == null 362 ? new HashSet () 363 : subgroups; 364 } 365 366 370 protected Set getSupergroups( 371 String qualifiedPrincipalName 372 ) throws ServiceException { 373 Set supergroups = (Set )this.supergroups.get(qualifiedPrincipalName); 374 return supergroups == null 375 ? new HashSet () 376 : supergroups; 377 } 378 379 protected Set getAllowedPrincipals( 381 DataproviderObject_1_0 principal, 382 DataproviderObject_1_0 user, 383 short accessLevel 384 ) { 385 if(!this.isActive || (accessLevel == SecurityKeys.ACCESS_LEVEL_GLOBAL)) { 387 return null; 388 } 389 Set allowedPrincipals = new HashSet (); 390 try { 391 if(accessLevel >= SecurityKeys.ACCESS_LEVEL_PRIVATE) { 393 allowedPrincipals.add( 394 this.plugin.getQualifiedPrincipalName(principal.path()) 395 ); 396 allowedPrincipals.add( 397 this.plugin.getQualifiedPrincipalName(user.path()) 398 ); 399 } 400 if((accessLevel == SecurityKeys.ACCESS_LEVEL_DEEP) || (accessLevel == SecurityKeys.ACCESS_LEVEL_BASIC)) { 402 for(Iterator i = principal.values("isMemberOf").iterator(); i.hasNext(); ) { 403 Path groupIdentity = (Path)i.next(); 404 allowedPrincipals.addAll( 405 this.getSubgroups(this.plugin.getQualifiedPrincipalName(groupIdentity)) 406 ); 407 } 408 for(Iterator i = principal.values("isMemberOf").iterator(); i.hasNext(); ) { 410 Path groupIdentity = (Path)i.next(); 411 allowedPrincipals.addAll( 412 this.getSupergroups(this.plugin.getQualifiedPrincipalName(groupIdentity)) 413 ); 414 } 415 } 416 if(accessLevel == SecurityKeys.ACCESS_LEVEL_DEEP) { 418 for(Iterator i = new HashSet (allowedPrincipals).iterator(); i.hasNext(); ) { 420 allowedPrincipals.addAll( 421 this.getSubgroups((String )i.next()) 422 ); 423 } 424 } 425 } 426 catch(ServiceException e) { 427 AppLog.warning("requesting principal can not be determined. Set of allowed principals = {}"); 428 return allowedPrincipals; 429 } 430 return allowedPrincipals.contains(SecurityKeys.ROOT_ADMINISTRATORS_GROUP) 432 ? null 433 : allowedPrincipals; 434 } 435 436 private static final int SECURITY_REAL_CHECK_RATE = 10000; 440 441 private final AccessControl_1 plugin; 442 private final Path realmIdentity; 443 444 private Map principals = new HashMap (); 445 private Map groups = null; 446 private boolean isActive = true; 447 private long securityRealmCheckAt = 0; 448 private String securityRealmModifiedAt = ""; 449 450 private Map subgroups = null; 453 private Map supergroups = null; 454 455 private final Map groupMapping = new HashMap (); 458 459 } 460 461 | Popular Tags |