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