001 package org.apache.archiva.web.startup; 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 022 import org.apache.archiva.common.ArchivaException; 023 import org.apache.archiva.configuration.ArchivaConfiguration; 024 import org.apache.archiva.configuration.ConfigurationNames; 025 import org.apache.archiva.configuration.ManagedRepositoryConfiguration; 026 import org.apache.archiva.redback.rbac.RBACManager; 027 import org.apache.archiva.redback.role.RoleManagerException; 028 import org.apache.archiva.redback.system.check.EnvironmentCheck; 029 import org.apache.archiva.security.common.ArchivaRoleConstants; 030 import org.apache.commons.collections.CollectionUtils; 031 import org.apache.commons.lang.StringUtils; 032 import org.apache.archiva.redback.rbac.RbacManagerException; 033 import org.apache.archiva.redback.rbac.UserAssignment; 034 import org.apache.archiva.redback.role.RoleManager; 035 import org.apache.archiva.redback.users.UserManager; 036 import org.apache.archiva.redback.components.registry.RegistryListener; 037 import org.apache.commons.lang.time.StopWatch; 038 import org.slf4j.Logger; 039 import org.slf4j.LoggerFactory; 040 import org.springframework.context.ApplicationContext; 041 import org.springframework.stereotype.Service; 042 043 import javax.annotation.PostConstruct; 044 import javax.inject.Inject; 045 import javax.inject.Named; 046 import java.util.ArrayList; 047 import java.util.HashMap; 048 import java.util.List; 049 import java.util.Map; 050 import java.util.Map.Entry; 051 052 /** 053 * ConfigurationSynchronization 054 */ 055 @Service 056 public class SecuritySynchronization 057 implements RegistryListener 058 { 059 private Logger log = LoggerFactory.getLogger( SecuritySynchronization.class ); 060 061 @Inject 062 private RoleManager roleManager; 063 064 @Inject 065 @Named(value = "rbacManager#cached") 066 private RBACManager rbacManager; 067 068 private Map<String, EnvironmentCheck> checkers; 069 070 @Inject 071 private ArchivaConfiguration archivaConfiguration; 072 073 @Inject 074 private ApplicationContext applicationContext; 075 076 @PostConstruct 077 public void initialize() 078 { 079 checkers = getBeansOfType( EnvironmentCheck.class ); 080 } 081 082 protected <T> Map<String, T> getBeansOfType( Class<T> clazz ) 083 { 084 //TODO do some caching here !!! 085 // olamy : with plexus we get only roleHint 086 // as per convention we named spring bean role#hint remove role# if exists 087 Map<String, T> springBeans = applicationContext.getBeansOfType( clazz ); 088 089 Map<String, T> beans = new HashMap<String, T>( springBeans.size() ); 090 091 for ( Entry<String, T> entry : springBeans.entrySet() ) 092 { 093 String key = StringUtils.substringAfterLast( entry.getKey(), "#" ); 094 beans.put( key, entry.getValue() ); 095 } 096 return beans; 097 } 098 099 public void afterConfigurationChange( org.apache.archiva.redback.components.registry.Registry registry, 100 String propertyName, Object propertyValue ) 101 { 102 if ( ConfigurationNames.isManagedRepositories( propertyName ) && propertyName.endsWith( ".id" ) ) 103 { 104 if ( propertyValue != null ) 105 { 106 syncRepoConfiguration( (String) propertyValue ); 107 } 108 } 109 } 110 111 public void beforeConfigurationChange( org.apache.archiva.redback.components.registry.Registry registry, 112 String propertyName, Object propertyValue ) 113 { 114 /* do nothing */ 115 } 116 117 private void synchConfiguration( List<ManagedRepositoryConfiguration> repos ) 118 { 119 // NOTE: Remote Repositories do not have roles or security placed around them. 120 121 for ( ManagedRepositoryConfiguration repoConfig : repos ) 122 { 123 syncRepoConfiguration( repoConfig.getId() ); 124 } 125 } 126 127 private void syncRepoConfiguration( String id ) 128 { 129 // manage roles for repositories 130 try 131 { 132 if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, id ) ) 133 { 134 roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, id ); 135 } 136 else 137 { 138 roleManager.verifyTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, id ); 139 } 140 141 if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, id ) ) 142 { 143 roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, id ); 144 } 145 else 146 { 147 roleManager.verifyTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, id ); 148 } 149 } 150 catch ( RoleManagerException e ) 151 { 152 // Log error. 153 log.error( "Unable to create roles for configured repositories: " + e.getMessage(), e ); 154 } 155 } 156 157 public void startup() 158 throws ArchivaException 159 { 160 executeEnvironmentChecks(); 161 162 synchConfiguration( archivaConfiguration.getConfiguration().getManagedRepositories() ); 163 archivaConfiguration.addChangeListener( this ); 164 165 if ( archivaConfiguration.isDefaulted() ) 166 { 167 assignRepositoryObserverToGuestUser( archivaConfiguration.getConfiguration().getManagedRepositories() ); 168 } 169 } 170 171 private void executeEnvironmentChecks() 172 throws ArchivaException 173 { 174 if ( ( checkers == null ) || CollectionUtils.isEmpty( checkers.values() ) ) 175 { 176 throw new ArchivaException( 177 "Unable to initialize the Redback Security Environment, " + "no Environment Check components found." ); 178 } 179 180 StopWatch stopWatch = new StopWatch(); 181 stopWatch.reset(); 182 stopWatch.start(); 183 184 List<String> violations = new ArrayList<String>(); 185 186 for ( Entry<String, EnvironmentCheck> entry : checkers.entrySet() ) 187 { 188 EnvironmentCheck check = entry.getValue(); 189 List<String> v = new ArrayList<String>(); 190 check.validateEnvironment( v ); 191 log.info( "Environment Check: " + entry.getKey() + " -> " + v.size() + " violation(s)" ); 192 for ( String s : v ) 193 { 194 violations.add( "[" + entry.getKey() + "] " + s ); 195 } 196 } 197 198 if ( CollectionUtils.isNotEmpty( violations ) ) 199 { 200 StringBuilder msg = new StringBuilder(); 201 msg.append( "EnvironmentCheck Failure.\n" ); 202 msg.append( "======================================================================\n" ); 203 msg.append( " ENVIRONMENT FAILURE !! \n" ); 204 msg.append( "\n" ); 205 206 for ( String violation : violations ) 207 { 208 msg.append( violation ).append( "\n" ); 209 } 210 211 msg.append( "\n" ); 212 msg.append( "======================================================================" ); 213 log.error( msg.toString() ); 214 215 throw new ArchivaException( "Unable to initialize Redback Security Environment, [" + violations.size() 216 + "] violation(s) encountered, See log for details." ); 217 } 218 219 stopWatch.stop(); 220 log.info( "time to execute all EnvironmentCheck: {} ms", stopWatch.getTime() ); 221 } 222 223 224 private void assignRepositoryObserverToGuestUser( List<ManagedRepositoryConfiguration> repos ) 225 { 226 for ( ManagedRepositoryConfiguration repoConfig : repos ) 227 { 228 String repoId = repoConfig.getId(); 229 230 String principal = UserManager.GUEST_USERNAME; 231 232 try 233 { 234 UserAssignment ua; 235 236 if ( rbacManager.userAssignmentExists( principal ) ) 237 { 238 ua = rbacManager.getUserAssignment( principal ); 239 } 240 else 241 { 242 ua = rbacManager.createUserAssignment( principal ); 243 } 244 245 ua.addRoleName( ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) ); 246 rbacManager.saveUserAssignment( ua ); 247 } 248 catch ( RbacManagerException e ) 249 { 250 log.warn( "Unable to add role [" + ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) + "] to " 251 + principal + " user.", e ); 252 } 253 } 254 } 255 }