001package org.apache.archiva.redback.rbac.ldap; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.archiva.redback.common.ldap.MappingException; 023import org.apache.archiva.redback.common.ldap.connection.LdapConnection; 024import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; 025import org.apache.archiva.redback.common.ldap.connection.LdapException; 026import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper; 027import org.apache.archiva.redback.common.ldap.role.LdapRoleMapperConfiguration; 028import org.apache.archiva.components.cache.Cache; 029import org.apache.archiva.redback.configuration.UserConfiguration; 030import org.apache.archiva.redback.configuration.UserConfigurationKeys; 031import org.apache.archiva.redback.rbac.AbstractRBACManager; 032import org.apache.archiva.redback.rbac.AbstractRole; 033import org.apache.archiva.redback.rbac.Operation; 034import org.apache.archiva.redback.rbac.Permission; 035import org.apache.archiva.redback.rbac.RBACManager; 036import org.apache.archiva.redback.rbac.RBACManagerListener; 037import org.apache.archiva.redback.rbac.RBACObjectAssertions; 038import org.apache.archiva.redback.rbac.RbacManagerException; 039import org.apache.archiva.redback.rbac.RbacObjectInvalidException; 040import org.apache.archiva.redback.rbac.RbacObjectNotFoundException; 041import org.apache.archiva.redback.rbac.RbacPermanentException; 042import org.apache.archiva.redback.rbac.Resource; 043import org.apache.archiva.redback.rbac.Role; 044import org.apache.archiva.redback.rbac.UserAssignment; 045import org.apache.archiva.redback.users.User; 046import org.apache.archiva.redback.users.UserManager; 047import org.apache.archiva.redback.users.UserManagerException; 048import org.apache.archiva.redback.users.ldap.ctl.LdapController; 049import org.apache.archiva.redback.users.ldap.ctl.LdapControllerException; 050import org.apache.commons.lang3.StringUtils; 051import org.slf4j.Logger; 052import org.slf4j.LoggerFactory; 053import org.springframework.stereotype.Service; 054 055import javax.annotation.PostConstruct; 056import javax.inject.Inject; 057import javax.inject.Named; 058import javax.naming.NamingException; 059import javax.naming.directory.DirContext; 060import java.util.ArrayList; 061import java.util.Collection; 062import java.util.Collections; 063import java.util.List; 064import java.util.Map; 065import java.util.Optional; 066import java.util.Set; 067import java.util.stream.Collectors; 068import java.util.stream.Stream; 069 070/** 071 * LdapRbacManager will read datas from ldap for mapping groups to role. 072 * Write operations will delegate to cached implementation. 073 * 074 * @author Olivier Lamy 075 */ 076@Service("rbacManager#ldap") 077public class LdapRbacManager 078 extends AbstractRBACManager 079 implements RBACManager, RBACManagerListener 080{ 081 082 private Logger log = LoggerFactory.getLogger( getClass() ); 083 084 @Inject 085 @Named(value = "rbacManager#cached") 086 private RBACManager rbacImpl; 087 088 @Inject 089 @Named(value = "ldapRoleMapper#default") 090 private LdapRoleMapper ldapRoleMapper; 091 092 @Inject 093 @Named(value = "userConfiguration#default") 094 private UserConfiguration userConf; 095 096 @Inject 097 @Named(value = "userManager#ldap") 098 private UserManager userManager; 099 100 @Inject 101 private LdapConnectionFactory ldapConnectionFactory; 102 103 @Inject 104 private LdapController ldapController; 105 106 @Inject 107 @Named(value = "ldapRoleMapperConfiguration#default") 108 private LdapRoleMapperConfiguration ldapRoleMapperConfiguration; 109 110 @Inject 111 @Named(value = "cache#ldapRoles") 112 private Cache<String, Role> rolesCache; 113 114 @Inject 115 @Named(value = "cache#userAssignments") 116 private Cache<String, UserAssignment> userAssignmentsCache; 117 118 private boolean writableLdap = false; 119 120 @Override 121 @PostConstruct 122 public void initialize() 123 { 124 this.writableLdap = userConf.getBoolean( UserConfigurationKeys.LDAP_WRITABLE, this.writableLdap ); 125 } 126 127 128 @Override 129 public void addChildRole( Role role, Role childRole ) 130 throws RbacObjectInvalidException, RbacManagerException 131 { 132 this.rbacImpl.addChildRole( role, childRole ); 133 } 134 135 @Override 136 public void addListener( RBACManagerListener listener ) 137 { 138 super.addListener( listener ); 139 this.rbacImpl.addListener( listener ); 140 } 141 142 @Override 143 public Operation createOperation( String name ) 144 throws RbacManagerException 145 { 146 return this.rbacImpl.createOperation( name ); 147 } 148 149 @Override 150 public Permission createPermission( String name ) 151 throws RbacManagerException 152 { 153 return this.rbacImpl.createPermission( name ); 154 } 155 156 @Override 157 public Permission createPermission( String name, String operationName, String resourceIdentifier ) 158 throws RbacManagerException 159 { 160 return this.rbacImpl.createPermission( name, operationName, resourceIdentifier ); 161 } 162 163 @Override 164 public Resource createResource( String identifier ) 165 throws RbacManagerException 166 { 167 return this.rbacImpl.createResource( identifier ); 168 } 169 170 @Override 171 public Role createRole( String id, String name ) 172 { 173 return this.rbacImpl.createRole( id, name ); 174 } 175 176 @Override 177 public UserAssignment createUserAssignment( String username ) 178 throws RbacManagerException 179 { 180 // TODO ldap cannot or isWritable ldap ? 181 return this.rbacImpl.createUserAssignment( username ); 182 } 183 184 @Override 185 public void eraseDatabase() 186 { 187 if ( writableLdap ) 188 { 189 LdapConnection ldapConnection = null; 190 DirContext context = null; 191 try 192 { 193 ldapConnection = ldapConnectionFactory.getConnection(); 194 context = ldapConnection.getDirContext(); 195 ldapRoleMapper.removeAllRoles( context ); 196 } 197 catch ( MappingException e ) 198 { 199 log.warn( "skip error removing all roles {}", e.getMessage() ); 200 } 201 catch ( LdapException e ) 202 { 203 log.warn( "skip error removing all roles {}", e.getMessage() ); 204 } 205 finally 206 { 207 closeContext( context ); 208 closeLdapConnection( ldapConnection ); 209 } 210 } 211 this.rolesCache.clear(); 212 this.userAssignmentsCache.clear(); 213 this.rbacImpl.eraseDatabase(); 214 } 215 216 /** 217 * @see org.apache.archiva.redback.rbac.RBACManager#getAllAssignableRoles() 218 */ 219 @Override 220 public List<Role> getAllAssignableRoles() 221 throws RbacManagerException 222 { 223 try 224 { 225 return ldapRoleMapperConfiguration.getLdapGroupMappings( ).entrySet( ).stream( ).flatMap( entry ->{ 226 if (entry.getValue()==null) { 227 return Stream.empty( ); 228 } else 229 { 230 return entry.getValue( ).stream( ).map( role -> new RoleImpl( entry.getKey( ) + role, role ) ); 231 } 232 } ).collect( Collectors.toList( ) ); 233 } 234 catch ( MappingException e ) 235 { 236 throw new RbacManagerException( e.getMessage(), e ); 237 } 238 } 239 240 @Override 241 public List<? extends Operation> getAllOperations() 242 throws RbacManagerException 243 { 244 return this.rbacImpl.getAllOperations(); 245 } 246 247 @Override 248 public List<? extends Permission> getAllPermissions() 249 throws RbacManagerException 250 { 251 return this.rbacImpl.getAllPermissions(); 252 } 253 254 @Override 255 public List<? extends Resource> getAllResources() 256 throws RbacManagerException 257 { 258 return this.rbacImpl.getAllResources(); 259 } 260 261 @Override 262 public List<Role> getAllRoles() 263 throws RbacManagerException 264 { 265 LdapConnection ldapConnection = null; 266 DirContext context = null; 267 try 268 { 269 ldapConnection = ldapConnectionFactory.getConnection(); 270 context = ldapConnection.getDirContext(); 271 272 List<String> groups = ldapRoleMapper.getAllGroups( context ); 273 return mapToRoles( groups ); 274 } 275 catch ( MappingException e ) 276 { 277 throw new RbacManagerException( e.getMessage(), e ); 278 } 279 catch ( LdapException e ) 280 { 281 throw new RbacManagerException( e.getMessage(), e ); 282 } 283 finally 284 { 285 closeContext( context ); 286 closeLdapConnection( ldapConnection ); 287 } 288 //return this.rbacImpl.getAllRoles(); 289 } 290 291 292 @Override 293 public List<UserAssignment> getAllUserAssignments() 294 throws RbacManagerException 295 { 296 LdapConnection ldapConnection = null; 297 DirContext context = null; 298 try 299 { 300 ldapConnection = ldapConnectionFactory.getConnection(); 301 context = ldapConnection.getDirContext(); 302 Map<String, Collection<String>> usersWithRoles = ldapController.findUsersWithRoles( context ); 303 List<UserAssignment> userAssignments = new ArrayList<UserAssignment>( usersWithRoles.size() ); 304 305 for ( Map.Entry<String, Collection<String>> entry : usersWithRoles.entrySet() ) 306 { 307 UserAssignment userAssignment = new UserAssignmentImpl( entry.getKey(), entry.getValue() ); 308 userAssignments.add( userAssignment ); 309 userAssignmentsCache.put( userAssignment.getPrincipal(), userAssignment ); 310 } 311 312 return userAssignments; 313 } 314 catch ( LdapControllerException e ) 315 { 316 throw new RbacManagerException( e.getMessage(), e ); 317 } 318 catch ( LdapException e ) 319 { 320 throw new RbacManagerException( e.getMessage(), e ); 321 } 322 finally 323 { 324 closeContext( context ); 325 closeLdapConnection( ldapConnection ); 326 } 327 } 328 329 protected void closeLdapConnection( LdapConnection ldapConnection ) 330 { 331 if ( ldapConnection != null ) 332 { 333 try 334 { 335 ldapConnection.close(); 336 } 337 catch ( NamingException e ) 338 { 339 log.error( "Could not close connection: {}", e.getMessage( ), e ); 340 } 341 } 342 } 343 344 protected void closeContext( DirContext context ) 345 { 346 if ( context != null ) 347 { 348 try 349 { 350 context.close(); 351 } 352 catch ( NamingException e ) 353 { 354 log.warn( "skip issue closing context: {}", e.getMessage() ); 355 } 356 } 357 } 358 359 /** 360 * public Map<String, List<Permission>> getAssignedPermissionMap( String username ) 361 * throws RbacManagerException 362 * { 363 * return this.rbacImpl.getAssignedPermissionMap( username ); 364 * }* 365 */ 366 367 /*public Set<Permission> getAssignedPermissions( String username ) 368 throws RbacObjectNotFoundException, RbacManagerException 369 { 370 // TODO here !! 371 return this.rbacImpl.getAssignedPermissions( username ); 372 }*/ 373 private List<Role> mapToRoles( List<String> groups ) 374 throws MappingException, RbacManagerException 375 { 376 if ( groups == null || groups.isEmpty() ) 377 { 378 return Collections.emptyList(); 379 } 380 final Map<String, Collection<String>> mappedGroups = ldapRoleMapperConfiguration.getLdapGroupMappings(); 381 try 382 { 383 return groups.stream( ).flatMap( group -> mappedGroups.get( group ) == null ? 384 ( this.ldapRoleMapper.isUseDefaultRoleName( ) ? Stream.of( this.buildRole( group, group ) ) : Stream.empty( ) ) 385 : mappedGroups.get( group ).stream( ).map( roleName -> this.buildRole( group + roleName, roleName ) ) ).collect( Collectors.toList( ) ); 386 } catch (RuntimeException e) { 387 if (e.getCause() instanceof RbacManagerException) 388 { 389 throw ( (RbacManagerException) e.getCause( ) ); 390 } else { 391 throw new MappingException( e.getMessage(), e ); 392 } 393 } 394 } 395 396 private Role buildRole( String groupId, String roleName ) 397 { 398 Role role = null; 399 try 400 { 401 role = this.rbacImpl.getRole( roleName ); 402 } 403 catch ( RbacObjectNotFoundException e ) 404 { 405 // if it's mapped role to a group it doesn't exist in jpa 406 } 407 catch ( RbacManagerException e ) 408 { 409 throw new RuntimeException( e ); 410 } 411 role = ( role == null ) ? new RoleImpl( groupId, roleName ) : role; 412 if ( role != null ) 413 { 414 rolesCache.put( role.getName(), role ); 415 416 } 417 return role; 418 } 419 420 protected List<String> getRealRoles() 421 throws RbacManagerException 422 { 423 List<? extends Role> roles = this.rbacImpl.getAllRoles(); 424 List<String> roleNames = new ArrayList<String>( roles.size() ); 425 for ( Role role : roles ) 426 { 427 roleNames.add( role.getName() ); 428 } 429 return roleNames; 430 } 431 432 @Override 433 public Collection<Role> getAssignedRoles( String username ) 434 throws RbacManagerException 435 { 436 437 LdapConnection ldapConnection = null; 438 DirContext context = null; 439 440 try 441 { 442 443 ldapConnection = ldapConnectionFactory.getConnection(); 444 context = ldapConnection.getDirContext(); 445 List<String> roleNames = ldapRoleMapper.getRoles( username, context, getRealRoles() ); 446 447 if ( roleNames.isEmpty() ) 448 { 449 return Collections.emptyList(); 450 } 451 452 List<Role> roles = new ArrayList<Role>( roleNames.size() ); 453 454 for ( String name : roleNames ) 455 { 456 roles.add( this.rbacImpl.getRole( name ) );// new RoleImpl( name ) ); 457 } 458 459 return roles; 460 } 461 catch ( MappingException e ) 462 { 463 throw new RbacManagerException( e.getMessage(), e ); 464 } 465 catch ( LdapException e ) 466 { 467 throw new RbacManagerException( e.getMessage(), e ); 468 } finally 469 { 470 closeContext( context ); 471 closeLdapConnection( ldapConnection ); 472 } 473 } 474 475 @Override 476 public Collection<Role> getAssignedRoles( UserAssignment userAssignment ) 477 throws RbacManagerException 478 { 479 return getAssignedRoles( userAssignment.getPrincipal() ); 480 } 481 482 @Override 483 public Map<String, ? extends Role> getChildRoleNames( Role role ) 484 throws RbacManagerException 485 { 486 return this.rbacImpl.getChildRoleNames( role ); 487 } 488 489 @Override 490 public Map<String, ? extends Role> getChildRoleIds( Role role ) throws RbacManagerException 491 { 492 return this.rbacImpl.getChildRoleIds( role ); 493 } 494 495 @Override 496 public Map<String, ? extends Role> getParentRoleNames( Role role ) 497 throws RbacManagerException 498 { 499 return this.rbacImpl.getParentRoleNames( role ); 500 } 501 502 @Override 503 public Map<String, ? extends Role> getParentRoleIds( Role role ) throws RbacManagerException 504 { 505 return this.rbacImpl.getParentRoleIds( role ); 506 } 507 508 // 509 // public Collection<Role> getEffectivelyAssignedRoles( String username ) 510 // throws RbacManagerException 511 // { 512 // TODO here !! 513 // return this.rbacImpl.getEffectivelyAssignedRoles( username ); 514 // } 515 516 //public Collection<Role> getEffectivelyUnassignedRoles( String username ) 517 //throws RbacManagerException 518 //{ 519 // TODO here !! 520 // return this.rbacImpl.getEffectivelyUnassignedRoles( username ); 521 // } 522 523 524 @Override 525 public Set<? extends Role> getEffectiveRoles( Role role ) 526 throws RbacManagerException 527 { 528 return this.rbacImpl.getEffectiveRoles( role ); 529 } 530 531 @Override 532 public Resource getGlobalResource() 533 throws RbacManagerException 534 { 535 return this.rbacImpl.getGlobalResource(); 536 } 537 538 @Override 539 public Operation getOperation( String operationName ) 540 throws RbacManagerException 541 { 542 return this.rbacImpl.getOperation( operationName ); 543 } 544 545 @Override 546 public Permission getPermission( String permissionName ) 547 throws RbacManagerException 548 { 549 return this.rbacImpl.getPermission( permissionName ); 550 } 551 552 @Override 553 public Resource getResource( String resourceIdentifier ) 554 throws RbacManagerException 555 { 556 return this.rbacImpl.getResource( resourceIdentifier ); 557 } 558 559 @Override 560 public Role getRole( String roleName ) 561 throws RbacManagerException 562 { 563 564 Role role = rolesCache.get( roleName ); 565 if ( role != null ) 566 { 567 return role; 568 } 569 if ( !checkIfLdapRole( roleName ) ) return null; 570 role = this.rbacImpl.getRole( roleName ); 571 if (role==null) 572 { 573 try 574 { 575 String groupName = ldapRoleMapperConfiguration.getLdapGroupMappings( ).entrySet( ).stream( ) 576 .filter( entry -> entry.getValue( ).contains( roleName ) ) 577 .map( entry -> entry.getKey( ) ).findFirst( ).orElseGet( String::new ); 578 role = new RoleImpl( groupName + roleName, roleName ); 579 } 580 catch ( MappingException e ) 581 { 582 role = new RoleImpl( roleName ); 583 } 584 }; 585 rolesCache.put( roleName, role ); 586 return role; 587 } 588 589 protected boolean checkIfLdapRole( String roleName ) throws RbacManagerException 590 { 591 LdapConnection ldapConnection = null; 592 DirContext context = null; 593 //verify it's a ldap group 594 try 595 { 596 ldapConnection = ldapConnectionFactory.getConnection(); 597 context = ldapConnection.getDirContext(); 598 if ( !ldapRoleMapper.hasRole( context, roleName ) ) 599 { 600 return false; 601 } 602 } 603 catch ( MappingException e ) 604 { 605 throw new RbacManagerException( e.getMessage(), e ); 606 } 607 catch ( LdapException e ) 608 { 609 throw new RbacManagerException( e.getMessage(), e ); 610 } finally 611 { 612 closeContext( context ); 613 closeLdapConnection( ldapConnection ); 614 } 615 return true; 616 } 617 618 @Override 619 public Role getRoleById( String id ) throws RbacObjectNotFoundException, RbacManagerException 620 { 621 Role role = rbacImpl.getRoleById( id ); 622 if (role==null) { 623 throw new RbacObjectNotFoundException( "Role with id " + id + " not found" ); 624 } else { 625 if (checkIfLdapRole( role.getName() )) { 626 return role; 627 } else { 628 return null; 629 } 630 } 631 } 632 633 @Override 634 public Map<String, ? extends Role> getRoles( Collection<String> roleNames ) 635 throws RbacManagerException 636 { 637 return this.rbacImpl.getRoles( roleNames ); 638 } 639 640 @Override 641 public Collection<Role> getUnassignedRoles( String username ) 642 throws RbacManagerException 643 { 644 LdapConnection ldapConnection = null; 645 646 DirContext context = null; 647 648 try 649 { 650 651 ldapConnection = ldapConnectionFactory.getConnection(); 652 653 context = ldapConnection.getDirContext(); 654 655 List<String> allRoles = ldapRoleMapper.getAllRoles( context ); 656 final List<String> userRoles = ldapRoleMapper.getRoles( username, context, getRealRoles() ); 657 658 List<Role> unassignedRoles = new ArrayList<Role>(); 659 660 for ( String roleName : allRoles ) 661 { 662 if ( !userRoles.contains( roleName ) ) 663 { 664 unassignedRoles.add( rbacImpl.getRole( roleName ) ); 665 } 666 } 667 return unassignedRoles; 668 } 669 catch ( MappingException e ) 670 { 671 throw new RbacManagerException( e.getMessage(), e ); 672 } 673 catch ( LdapException e ) 674 { 675 throw new RbacManagerException( e.getMessage(), e ); 676 } 677 finally 678 { 679 closeContext( context ); 680 closeLdapConnection( ldapConnection ); 681 } 682 } 683 684 @Override 685 public UserAssignment getUserAssignment( String username ) 686 throws RbacManagerException 687 { 688 UserAssignment ua = userAssignmentsCache.get( username ); 689 if ( ua != null ) 690 { 691 return ua; 692 } 693 LdapConnection ldapConnection = null; 694 DirContext context = null; 695 try 696 { 697 ldapConnection = ldapConnectionFactory.getConnection(); 698 context = ldapConnection.getDirContext(); 699 List<String> roles = ldapRoleMapper.getRoles( username, context, getRealRoles() ) 700 .stream( ).map( roleName -> { 701 try 702 { 703 return Optional.of( rbacImpl.getRole( roleName ).getId() ); 704 } 705 catch ( RbacManagerException e ) 706 { 707 return Optional.<String>empty( ); 708 } 709 } ).filter( Optional::isPresent ).map( Optional::get ).collect( Collectors.toList() ); 710 711 ua = new UserAssignmentImpl( username, roles ); 712 713 userAssignmentsCache.put( username, ua ); 714 715 return ua; 716 } 717 catch ( MappingException e ) 718 { 719 throw new RbacManagerException( e.getMessage(), e ); 720 } 721 catch ( LdapException e ) 722 { 723 throw new RbacManagerException( e.getMessage(), e ); 724 } 725 finally 726 { 727 closeContext( context ); 728 closeLdapConnection( ldapConnection ); 729 } 730 731 //return this.rbacImpl.getUserAssignment( username ); 732 } 733 734 @Override 735 public List<? extends UserAssignment> getUserAssignmentsForRoles( Collection<String> roleIds ) 736 throws RbacManagerException 737 { 738 // TODO from ldap 739 return this.rbacImpl.getUserAssignmentsForRoles( roleIds ); 740 } 741 742 @Override 743 public boolean operationExists( Operation operation ) 744 { 745 return this.rbacImpl.operationExists( operation ); 746 } 747 748 @Override 749 public boolean operationExists( String name ) 750 { 751 return this.rbacImpl.operationExists( name ); 752 } 753 754 @Override 755 public boolean permissionExists( Permission permission ) 756 { 757 return this.rbacImpl.permissionExists( permission ); 758 } 759 760 @Override 761 public boolean permissionExists( String name ) 762 { 763 return this.rbacImpl.permissionExists( name ); 764 } 765 766 @Override 767 public void rbacInit( boolean freshdb ) 768 { 769 if ( rbacImpl instanceof RBACManagerListener ) 770 { 771 ( (RBACManagerListener) this.rbacImpl ).rbacInit( freshdb ); 772 } 773 } 774 775 @Override 776 public void rbacPermissionRemoved( Permission permission ) 777 { 778 if ( rbacImpl instanceof RBACManagerListener ) 779 { 780 ( (RBACManagerListener) this.rbacImpl ).rbacPermissionRemoved( permission ); 781 } 782 783 } 784 785 @Override 786 public void rbacPermissionSaved( Permission permission ) 787 { 788 if ( rbacImpl instanceof RBACManagerListener ) 789 { 790 ( (RBACManagerListener) this.rbacImpl ).rbacPermissionSaved( permission ); 791 } 792 793 } 794 795 @Override 796 public void rbacRoleRemoved( Role role ) 797 { 798 if ( rbacImpl instanceof RBACManagerListener ) 799 { 800 ( (RBACManagerListener) this.rbacImpl ).rbacRoleRemoved( role ); 801 } 802 803 } 804 805 @Override 806 public void rbacRoleSaved( Role role ) 807 { 808 if ( rbacImpl instanceof RBACManagerListener ) 809 { 810 ( (RBACManagerListener) this.rbacImpl ).rbacRoleSaved( role ); 811 } 812 813 } 814 815 @Override 816 public void rbacUserAssignmentRemoved( UserAssignment userAssignment ) 817 { 818 if ( rbacImpl instanceof RBACManagerListener ) 819 { 820 ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentRemoved( userAssignment ); 821 } 822 823 } 824 825 @Override 826 public void rbacUserAssignmentSaved( UserAssignment userAssignment ) 827 { 828 if ( rbacImpl instanceof RBACManagerListener ) 829 { 830 ( (RBACManagerListener) this.rbacImpl ).rbacUserAssignmentSaved( userAssignment ); 831 } 832 833 } 834 835 @Override 836 public void removeListener( RBACManagerListener listener ) 837 { 838 this.rbacImpl.removeListener( listener ); 839 } 840 841 @Override 842 public void removeOperation( Operation operation ) 843 throws RbacManagerException 844 { 845 this.rbacImpl.removeOperation( operation ); 846 } 847 848 @Override 849 public void removeOperation( String operationName ) 850 throws RbacManagerException 851 { 852 this.rbacImpl.removeOperation( operationName ); 853 } 854 855 @Override 856 public void removePermission( Permission permission ) 857 throws RbacManagerException 858 { 859 this.rbacImpl.removePermission( permission ); 860 } 861 862 @Override 863 public void removePermission( String permissionName ) 864 throws RbacManagerException 865 { 866 this.rbacImpl.removePermission( permissionName ); 867 } 868 869 @Override 870 public void removeResource( Resource resource ) 871 throws RbacManagerException 872 { 873 this.rbacImpl.removeResource( resource ); 874 } 875 876 @Override 877 public void removeResource( String resourceIdentifier ) 878 throws RbacManagerException 879 { 880 this.rbacImpl.removeResource( resourceIdentifier ); 881 } 882 883 @Override 884 public void removeRole( Role role ) 885 throws RbacManagerException 886 { 887 RBACObjectAssertions.assertValid( role ); 888 889 if ( role.isPermanent() ) 890 { 891 throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" ); 892 } 893 rolesCache.remove( role.getName() ); 894 if ( writableLdap ) 895 { 896 LdapConnection ldapConnection = null; 897 DirContext context = null; 898 try 899 { 900 ldapConnection = ldapConnectionFactory.getConnection(); 901 context = ldapConnection.getDirContext(); 902 ldapRoleMapper.removeRole( role.getName(), context ); 903 } 904 catch ( MappingException e ) 905 { 906 throw new RbacManagerException( e.getMessage(), e ); 907 } 908 catch ( LdapException e ) 909 { 910 throw new RbacManagerException( e.getMessage(), e ); 911 } finally { 912 closeContext( context ); 913 closeLdapConnection( ldapConnection ); 914 } 915 fireRbacRoleRemoved( role ); 916 } 917 } 918 919 @Override 920 public void removeRole( String roleName ) 921 throws RbacManagerException 922 { 923 if ( roleName == null ) 924 { 925 return; 926 } 927 removeRole( new RoleImpl( roleName ) ); 928 } 929 930 @Override 931 public void removeUserAssignment( String username ) 932 throws RbacManagerException 933 { 934 // TODO ldap cannot or isWritable ldap ? 935 userAssignmentsCache.remove( username ); 936 this.rbacImpl.removeUserAssignment( username ); 937 } 938 939 @Override 940 public void removeUserAssignment( UserAssignment userAssignment ) 941 throws RbacManagerException 942 { 943 if ( userAssignment != null ) 944 { 945 userAssignmentsCache.remove( userAssignment.getPrincipal() ); 946 } 947 // TODO ldap cannot or isWritable ldap ? 948 this.rbacImpl.removeUserAssignment( userAssignment ); 949 } 950 951 @Override 952 public boolean resourceExists( Resource resource ) 953 { 954 return this.rbacImpl.resourceExists( resource ); 955 } 956 957 @Override 958 public boolean resourceExists( String identifier ) 959 { 960 return this.rbacImpl.resourceExists( identifier ); 961 } 962 963 @Override 964 public boolean roleExists( Role role ) 965 throws RbacManagerException 966 { 967 if ( role == null ) 968 { 969 return false; 970 } 971 return roleExists( role.getName() ); 972 } 973 974 @Override 975 public boolean roleExists( String name ) 976 throws RbacManagerException 977 { 978 if ( StringUtils.isEmpty( name ) ) 979 { 980 return false; 981 } 982 if ( rolesCache.get( name ) != null ) 983 { 984 return true; 985 } 986 LdapConnection ldapConnection = null; 987 DirContext context = null; 988 try 989 { 990 ldapConnection = ldapConnectionFactory.getConnection(); 991 context = ldapConnection.getDirContext(); 992 if ( rolesCache.hasKey( name ) ) 993 { 994 return true; 995 } 996 return ldapRoleMapper.hasRole( context, name ); 997 } 998 catch ( MappingException e ) 999 { 1000 throw new RbacManagerException( e.getMessage(), e ); 1001 } 1002 catch ( LdapException e ) 1003 { 1004 throw new RbacManagerException( e.getMessage(), e ); 1005 } 1006 finally 1007 { 1008 closeContext( context ); 1009 closeLdapConnection( ldapConnection ); 1010 } 1011 } 1012 1013 @Override 1014 public boolean roleExistsById( String id ) throws RbacManagerException 1015 { 1016 Role role = rbacImpl.getRoleById( id ); 1017 if (role==null) { 1018 return false; 1019 } else { 1020 return roleExists( role.getName() ); 1021 } 1022 } 1023 1024 @Override 1025 public Operation saveOperation( Operation operation ) 1026 throws RbacManagerException 1027 { 1028 return this.rbacImpl.saveOperation( operation ); 1029 } 1030 1031 @Override 1032 public Permission savePermission( Permission permission ) 1033 throws RbacManagerException 1034 { 1035 return this.rbacImpl.savePermission( permission ); 1036 } 1037 1038 @Override 1039 public Resource saveResource( Resource resource ) 1040 throws RbacManagerException 1041 { 1042 return this.rbacImpl.saveResource( resource ); 1043 } 1044 1045 @Override 1046 public synchronized Role saveRole( Role role ) 1047 throws RbacManagerException 1048 { 1049 if ( writableLdap ) 1050 { 1051 LdapConnection ldapConnection = null; 1052 DirContext context = null; 1053 try 1054 { 1055 ldapConnection = ldapConnectionFactory.getConnection(); 1056 context = ldapConnection.getDirContext(); 1057 ldapRoleMapper.saveRole( role.getName(), context ); 1058 1059 if ( !role.getChildRoleNames().isEmpty() ) 1060 { 1061 for ( String roleName : role.getChildRoleNames() ) 1062 { 1063 ldapRoleMapper.saveRole( roleName, context ); 1064 } 1065 } 1066 fireRbacRoleSaved( role ); 1067 } 1068 catch ( MappingException e ) 1069 { 1070 throw new RbacManagerException( e.getMessage(), e ); 1071 } 1072 catch ( LdapException e ) 1073 { 1074 throw new RbacManagerException( e.getMessage(), e ); 1075 } 1076 } 1077 role = this.rbacImpl.saveRole( role ); 1078 rolesCache.put( role.getName(), role ); 1079 1080 return role; 1081 //return new RoleImpl( role.getName(), role.getPermissions() ); 1082 } 1083 1084 @Override 1085 public synchronized void saveRoles( Collection<Role> roles ) 1086 throws RbacManagerException 1087 { 1088 if ( writableLdap ) 1089 { 1090 LdapConnection ldapConnection = null; 1091 DirContext context = null; 1092 try 1093 { 1094 1095 ldapConnection = ldapConnectionFactory.getConnection(); 1096 context = ldapConnection.getDirContext(); 1097 for ( Role role : roles ) 1098 { 1099 ldapRoleMapper.saveRole( role.getName(), context ); 1100 fireRbacRoleSaved( role ); 1101 } 1102 } 1103 catch ( MappingException e ) 1104 { 1105 throw new RbacManagerException( e.getMessage(), e ); 1106 } 1107 catch ( LdapException e ) 1108 { 1109 throw new RbacManagerException( e.getMessage(), e ); 1110 } 1111 } 1112 this.rbacImpl.saveRoles( roles ); 1113 1114 } 1115 1116 @Override 1117 public UserAssignment saveUserAssignment( UserAssignment userAssignment ) 1118 throws RbacManagerException 1119 { 1120 LdapConnection ldapConnection = null; 1121 DirContext context = null; 1122 try 1123 { 1124 if ( !userManager.userExists( userAssignment.getPrincipal() ) ) 1125 { 1126 User user = userManager.createUser( userAssignment.getPrincipal(), null, null ); 1127 userManager.addUser( user ); 1128 } 1129 ldapConnection = ldapConnectionFactory.getConnection(); 1130 context = ldapConnection.getDirContext(); 1131 List<String> allRoles = ldapRoleMapper.getAllRoles( context ); 1132 1133 List<String> currentUserRoles = 1134 ldapRoleMapper.getRoles( userAssignment.getPrincipal(), context, getRealRoles() ); 1135 Map<String, String> currentUserIds = currentUserRoles.stream( ).map( roleName -> { 1136 try 1137 { 1138 return Optional.of( rbacImpl.getRole( roleName ) ); 1139 } 1140 catch ( RbacManagerException e ) 1141 { 1142 return Optional.<Role>empty( ); 1143 } 1144 } ).filter( Optional::isPresent ).map(Optional::get) 1145 .collect( Collectors.toMap( Role::getName, Role::getId ) ); 1146 1147 for ( String roleId : userAssignment.getRoleIds() ) 1148 { 1149 Role rbacRole = rbacImpl.getRoleById( roleId ); 1150 String roleName = rbacRole.getName( ); 1151 if ( !currentUserRoles.contains( roleName ) && writableLdap ) 1152 { 1153 // role exists in ldap ? 1154 if ( !allRoles.contains( roleName ) ) 1155 { 1156 ldapRoleMapper.saveRole( roleName, context ); 1157 allRoles.add( roleName ); 1158 } 1159 ldapRoleMapper.saveUserRole( roleName, userAssignment.getPrincipal(), context ); 1160 currentUserRoles.add( roleName ); 1161 currentUserIds.put( roleName, rbacRole.getId( ) ); 1162 } 1163 } 1164 1165 for ( String roleName : currentUserRoles ) 1166 { 1167 if ( !userAssignment.getRoleIds().contains( currentUserIds.get(roleName) ) && writableLdap ) 1168 { 1169 ldapRoleMapper.removeUserRole( roleName, userAssignment.getPrincipal(), context ); 1170 } 1171 } 1172 1173 userAssignmentsCache.put( userAssignment.getPrincipal(), userAssignment ); 1174 return userAssignment; 1175 } 1176 catch ( UserManagerException e ) 1177 { 1178 throw new RbacManagerException( e.getMessage(), e ); 1179 } 1180 catch ( MappingException e ) 1181 { 1182 throw new RbacManagerException( e.getMessage(), e ); 1183 } 1184 catch ( LdapException e ) 1185 { 1186 throw new RbacManagerException( e.getMessage(), e ); 1187 } 1188 finally 1189 { 1190 closeContext( context ); 1191 closeLdapConnection( ldapConnection ); 1192 } 1193 } 1194 1195 @Override 1196 public boolean userAssignmentExists( String principal ) 1197 { 1198 if ( userAssignmentsCache.hasKey( principal ) ) 1199 { 1200 return true; 1201 } 1202 LdapConnection ldapConnection = null; 1203 DirContext context = null; 1204 try 1205 { 1206 ldapConnection = ldapConnectionFactory.getConnection(); 1207 context = ldapConnection.getDirContext(); 1208 List<String> roles = ldapRoleMapper.getRoles( principal, context, getRealRoles() ); 1209 if ( roles == null || roles.isEmpty() ) 1210 { 1211 return false; 1212 } 1213 return true; 1214 } 1215 catch ( RbacManagerException e ) 1216 { 1217 log.warn( "fail to call userAssignmentExists: {}", e.getMessage() ); 1218 } 1219 catch ( LdapException e ) 1220 { 1221 log.warn( "fail to call userAssignmentExists: {}", e.getMessage() ); 1222 } 1223 catch ( MappingException e ) 1224 { 1225 log.warn( "fail to call userAssignmentExists: {}", e.getMessage() ); 1226 } 1227 finally 1228 { 1229 closeContext( context ); 1230 closeLdapConnection( ldapConnection ); 1231 } 1232 return false; 1233 } 1234 1235 @Override 1236 public boolean userAssignmentExists( UserAssignment assignment ) 1237 { 1238 if ( assignment == null ) 1239 { 1240 return false; 1241 } 1242 return this.userAssignmentExists( assignment.getPrincipal() ); 1243 } 1244 1245 public RBACManager getRbacImpl() 1246 { 1247 return rbacImpl; 1248 } 1249 1250 public void setRbacImpl( RBACManager rbacImpl ) 1251 { 1252 this.rbacImpl = rbacImpl; 1253 } 1254 1255 public boolean isWritableLdap() 1256 { 1257 return writableLdap; 1258 } 1259 1260 public void setWritableLdap( boolean writableLdap ) 1261 { 1262 this.writableLdap = writableLdap; 1263 } 1264 1265 public LdapRoleMapper getLdapRoleMapper() 1266 { 1267 return ldapRoleMapper; 1268 } 1269 1270 public void setLdapRoleMapper( LdapRoleMapper ldapRoleMapper ) 1271 { 1272 this.ldapRoleMapper = ldapRoleMapper; 1273 } 1274 1275 private static class RoleImpl 1276 extends AbstractRole 1277 { 1278 private String name; 1279 1280 private String description; 1281 private String id=""; 1282 private String modelId=""; 1283 private boolean isTemplateInstance=false; 1284 private String resource=""; 1285 1286 private List<Permission> permissions = new ArrayList<>(); 1287 1288 private List<String> childRoleNames = new ArrayList<>(); 1289 private List<String> childRoleIds = new ArrayList<>( ); 1290 1291 private RoleImpl( String name ) 1292 { 1293 this.name = name; 1294 this.id = name; 1295 } 1296 1297 private RoleImpl(String id, String name) { 1298 this.id = id; 1299 this.name = name; 1300 } 1301 1302 private RoleImpl( String name, List<Permission> permissions ) 1303 { 1304 this.name = name; 1305 this.permissions = permissions; 1306 } 1307 1308 @Override 1309 public void addPermission( Permission permission ) 1310 { 1311 this.permissions.add( permission ); 1312 } 1313 1314 @Override 1315 public void addChildRoleName( String name ) 1316 { 1317 this.childRoleNames.add( name ); 1318 } 1319 1320 @Override 1321 public List<String> getChildRoleNames() 1322 { 1323 return this.childRoleNames; 1324 } 1325 1326 @Override 1327 public void addChildRoleId( String id ) 1328 { 1329 this.childRoleIds.add( id ); 1330 } 1331 1332 @Override 1333 public List<String> getChildRoleIds( ) 1334 { 1335 return this.childRoleIds; 1336 } 1337 1338 @Override 1339 public String getDescription() 1340 { 1341 return this.description; 1342 } 1343 1344 @Override 1345 public String getName() 1346 { 1347 return this.name; 1348 } 1349 1350 @Override 1351 public List<Permission> getPermissions() 1352 { 1353 return this.permissions; 1354 } 1355 1356 @Override 1357 public boolean isAssignable() 1358 { 1359 return true; 1360 } 1361 1362 @Override 1363 public void removePermission( Permission permission ) 1364 { 1365 this.permissions.remove( permission ); 1366 } 1367 1368 @Override 1369 public void setAssignable( boolean assignable ) 1370 { 1371 // no op 1372 } 1373 1374 @Override 1375 public void setChildRoleNames( List<String> names ) 1376 { 1377 this.childRoleNames = names; 1378 } 1379 1380 @Override 1381 public void setChildRoleIds( List<String> ids ) 1382 { 1383 1384 } 1385 1386 @Override 1387 public void setDescription( String description ) 1388 { 1389 this.description = description; 1390 } 1391 1392 @Override 1393 public void setName( String name ) 1394 { 1395 this.name = name; 1396 } 1397 1398 @Override 1399 public void setPermissions( List<Permission> permissions ) 1400 { 1401 this.permissions = permissions; 1402 } 1403 1404 @Override 1405 public boolean isPermanent() 1406 { 1407 return true; 1408 } 1409 1410 @Override 1411 public void setPermanent( boolean permanent ) 1412 { 1413 // no op 1414 } 1415 1416 @Override 1417 public String toString() 1418 { 1419 final StringBuilder sb = new StringBuilder(); 1420 sb.append( "RoleImpl" ); 1421 sb.append( "{name='" ).append( name ).append( '\'' ); 1422 sb.append( '}' ); 1423 return sb.toString(); 1424 } 1425 1426 @Override 1427 public boolean equals( Object o ) 1428 { 1429 if ( this == o ) 1430 { 1431 return true; 1432 } 1433 if ( o == null || getClass() != o.getClass() ) 1434 { 1435 return false; 1436 } 1437 1438 RoleImpl role = (RoleImpl) o; 1439 1440 if ( name != null ? !name.equals( role.name ) : role.name != null ) 1441 { 1442 return false; 1443 } 1444 1445 return true; 1446 } 1447 1448 @Override 1449 public int hashCode() 1450 { 1451 return name != null ? name.hashCode() : 0; 1452 } 1453 1454 1455 @Override 1456 public String getId( ) 1457 { 1458 return id; 1459 } 1460 1461 @Override 1462 public void setId( String id ) 1463 { 1464 if (id==null) { 1465 this.id = ""; 1466 } else 1467 { 1468 this.id = id; 1469 } 1470 } 1471 1472 @Override 1473 public String getModelId( ) 1474 { 1475 return modelId; 1476 } 1477 1478 @Override 1479 public void setModelId( String modelId ) 1480 { 1481 if (modelId==null) { 1482 this.modelId = ""; 1483 } else 1484 { 1485 this.modelId = modelId; 1486 } 1487 } 1488 1489 @Override 1490 public boolean isTemplateInstance( ) 1491 { 1492 return isTemplateInstance; 1493 } 1494 1495 @Override 1496 public void setTemplateInstance( boolean templateInstance ) 1497 { 1498 isTemplateInstance = templateInstance; 1499 } 1500 1501 @Override 1502 public String getResource( ) 1503 { 1504 return resource; 1505 } 1506 1507 @Override 1508 public void setResource( String resource ) 1509 { 1510 if (resource==null) { 1511 this.resource = ""; 1512 } else 1513 { 1514 this.resource = resource; 1515 } 1516 } 1517 1518 1519 } 1520 1521 private static class UserAssignmentImpl 1522 implements UserAssignment 1523 { 1524 private String username; 1525 1526 private List<String> roleIds; 1527 1528 private boolean permanent; 1529 1530 private UserAssignmentImpl( String username, Collection<String> roleIds ) 1531 { 1532 this.username = username; 1533 1534 if ( roleIds == null ) 1535 { 1536 this.roleIds = new ArrayList<>( ); 1537 } 1538 else 1539 { 1540 this.roleIds = new ArrayList<>( roleIds ); 1541 } 1542 } 1543 1544 @Override 1545 public String getPrincipal() 1546 { 1547 return this.username; 1548 } 1549 1550 @Override 1551 public List<String> getRoleNames() 1552 { 1553 return this.roleIds; 1554 } 1555 1556 @Override 1557 public List<String> getRoleIds( ) 1558 { 1559 return this.roleIds; 1560 } 1561 1562 @Override 1563 public void addRoleName( Role role ) 1564 { 1565 if ( role == null ) 1566 { 1567 return; 1568 } 1569 this.roleIds.add( role.getName() ); 1570 } 1571 1572 @Override 1573 public void addRoleName( String roleName ) 1574 { 1575 if ( roleName == null ) 1576 { 1577 return; 1578 } 1579 this.roleIds.add( roleName ); 1580 } 1581 1582 @Override 1583 public void addRoleId( Role role ) 1584 { 1585 if ( role == null ) 1586 { 1587 return; 1588 } 1589 this.roleIds.add( role.getId() ); 1590 } 1591 1592 @Override 1593 public void addRoleId( String roleId ) 1594 { 1595 if ( roleId == null ) 1596 { 1597 return; 1598 } 1599 this.roleIds.add( roleId ); 1600 } 1601 1602 @Override 1603 public void removeRoleName( Role role ) 1604 { 1605 if ( role == null ) 1606 { 1607 return; 1608 } 1609 this.roleIds.remove( role.getName() ); 1610 } 1611 1612 @Override 1613 public void removeRoleName( String roleName ) 1614 { 1615 if ( roleName == null ) 1616 { 1617 return; 1618 } 1619 this.roleIds.remove( roleName ); 1620 } 1621 1622 @Override 1623 public void removeRoleId( Role role ) 1624 { 1625 if ( role == null ) 1626 { 1627 return; 1628 } 1629 this.roleIds.remove( role.getId() ); 1630 } 1631 1632 @Override 1633 public void removeRoleId( String roleId ) 1634 { 1635 if ( roleId == null ) 1636 { 1637 return; 1638 } 1639 this.roleIds.remove( roleId ); 1640 } 1641 1642 @Override 1643 public void setPrincipal( String principal ) 1644 { 1645 this.username = principal; 1646 } 1647 1648 @Override 1649 public void setRoleNames( List<String> roles ) 1650 { 1651 this.roleIds = roles; 1652 } 1653 1654 @Override 1655 public void setRoleIds( List<String> roles ) 1656 { 1657 this.roleIds = roles; 1658 } 1659 1660 @Override 1661 public boolean isPermanent() 1662 { 1663 return this.permanent; 1664 } 1665 1666 @Override 1667 public void setPermanent( boolean permanent ) 1668 { 1669 this.permanent = permanent; 1670 } 1671 1672 @Override 1673 public String toString() 1674 { 1675 final StringBuilder sb = new StringBuilder(); 1676 sb.append( "UserAssignmentImpl" ); 1677 sb.append( "{username='" ).append( username ).append( '\'' ); 1678 sb.append( ", roleNames=" ).append( roleIds ); 1679 sb.append( ", permanent=" ).append( permanent ); 1680 sb.append( '}' ); 1681 return sb.toString(); 1682 } 1683 } 1684 1685 1686 @Override 1687 public boolean isFinalImplementation() 1688 { 1689 return true; 1690 } 1691 1692 @Override 1693 public String getDescriptionKey() 1694 { 1695 return "archiva.redback.rbacmanager.ldap"; 1696 } 1697 1698 @Override 1699 public boolean isReadOnly() 1700 { 1701 return !writableLdap; 1702 } 1703}