This project has retired. For details please refer to its Attic page.
Source code
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.components.registry.RegistryListener;
027import org.apache.archiva.redback.rbac.RBACManager;
028import org.apache.archiva.redback.rbac.RbacManagerException;
029import org.apache.archiva.redback.rbac.UserAssignment;
030import org.apache.archiva.redback.role.RoleManager;
031import org.apache.archiva.redback.role.RoleManagerException;
032import org.apache.archiva.redback.system.check.EnvironmentCheck;
033import org.apache.archiva.redback.users.UserManager;
034import org.apache.archiva.security.common.ArchivaRoleConstants;
035import org.apache.commons.collections4.CollectionUtils;
036import org.apache.commons.lang3.StringUtils;
037import org.apache.commons.lang3.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.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.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}