Project

General

Profile

Download (7.18 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2016 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9
package eu.etaxonomy.cdm.remote.config;
10

    
11
import java.io.File;
12
import java.io.FileInputStream;
13
import java.io.IOException;
14
import java.util.Properties;
15

    
16
import org.apache.commons.io.FileUtils;
17
import org.springframework.beans.factory.annotation.Autowired;
18
import org.springframework.context.annotation.Configuration;
19
import org.springframework.context.annotation.Import;
20
import org.springframework.core.annotation.Order;
21
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
22
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
23
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
24
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
25
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
26
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
27

    
28
import eu.etaxonomy.cdm.common.ConfigFileUtil;
29

    
30
/**
31
 *
32
 * <b>NOTE</b> on nested @Configuration classes:
33
 *
34
 * When bootstrapping such an arrangement, only the outer class need be registered against the application context.
35
 * By virtue of being a nested @Configuration class, DatabaseConfig will be registered automatically. This avoids
36
 * the need to use an @Import annotation when the relationship between AppConfig DatabaseConfig is already implicitly
37
 * clear.
38
 *
39
 * @author a.kohlbecker
40
 * @since Oct 6, 2016
41
 *
42
 */
43
@EnableWebSecurity
44
@Import(OAuth2ServerConfiguration.class)
45
public class MultiWebSecurityConfiguration {
46

    
47
    public static final String MANAGE_CLIENT = "MANAGE_CLIENT";
48

    
49
    public static final String ROLE_MANAGE_CLIENT = "ROLE_" + MANAGE_CLIENT;
50

    
51
    private static final String MANAGING_USERS_PROPERTIES = "managing-users.properties";
52

    
53
    /**
54
     * Check for full authentication for remoting services
55
     * @author a.kohlbecker
56
     * @since Oct 6, 2016
57
     *
58
     */
59
    @Configuration
60
    @Order(2)
61
    public static class RemotingWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
62
        @Override
63
        protected void configure(HttpSecurity http) throws Exception {
64
              // @formatter:off
65
                http
66
             .anonymous().disable()
67
             .antMatcher("/remoting/**")
68
                 .authorizeRequests().anyRequest().access("hasAnyRole('ROLE_ADMIN', 'ROLE_PROJECT_MANAGER', 'ROLE_REMOTING')")
69
                 .and()
70
             .csrf().disable()
71
             .httpBasic();
72
             // @formatter:on
73
        }
74
    }
75

    
76
    /**
77
     * Require full authentication on the OAuth2 authorization service
78
     * so that the user is requested to provide his credentials.
79
     *
80
     * @author a.kohlbecker
81
     * @since Jan 16, 2017
82
     *
83
     */
84
    @Configuration
85
    @Order(1)
86
    public static class LoginWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
87
        @Override
88
        protected void configure(HttpSecurity http) throws Exception {
89
              // @formatter:off
90
                http
91
             .anonymous().disable()
92
             .antMatcher("/oauth/authorize")
93
                 .authorizeRequests().anyRequest().fullyAuthenticated()
94
                 .and()
95
             .csrf().disable()
96
             .httpBasic();
97
             // @formatter:on
98
        }
99
    }
100

    
101
    /**
102
     * Allow anonymous authentication for all other services.
103
     *
104
     * <b>NOTE:</b> Further access restrictions are defined
105
     * in the OAuth2ServerConfiguration.
106
     *
107
     * @author a.kohlbecker
108
     * @since Oct 6, 2016
109
     *
110
     */
111
    @Configuration
112
    public static class DefaultWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
113

    
114
        @Override
115
        protected void configure(HttpSecurity http) throws Exception {
116
              // @formatter:off
117
                http
118
             .anonymous().and()
119
             .antMatcher("/**")
120
             .csrf().disable()
121
             .httpBasic();
122
             // @formatter:on
123
        }
124
    }
125

    
126
    @Autowired
127
    public void configureGlobal(AuthenticationManagerBuilder auth, DaoAuthenticationProvider daoAuthenticationProvider) throws Exception {
128

    
129
        // add the DaoAuthenticationProvider which is defined in
130
        // /cdmlib-services/src/main/resources/eu/etaxonomy/cdm/services_security.xml
131
        // if not added here it will not be added to the context as long as we are doing the
132
        // configuration explicitly here.
133
        auth.authenticationProvider(daoAuthenticationProvider);
134

    
135
        // Add an inMemoryUserManager to  enable access to the global ROLE_MANAGE_CLIENTs.
136
        // This is the casue for the need to do the configuration explicitly.
137
        InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthConf = auth.inMemoryAuthentication();
138
        File managingUsersFile = new File(ConfigFileUtil.getCdmHomeDir(), MANAGING_USERS_PROPERTIES);
139
        if(!managingUsersFile.exists()){
140
            makeManagingUsersPropertiesFile(managingUsersFile);
141
        }
142
        Properties users = new Properties();
143
        users.load(new FileInputStream(managingUsersFile));
144
        for(Object userName : users.keySet()){
145
            inMemoryAuthConf.withUser(userName.toString()).password(users.get(userName).toString()).roles(MANAGE_CLIENT);
146
        }
147
    }
148

    
149
    /**
150
     * @param globalManagementClients
151
     * @throws IOException
152
     */
153
    private void makeManagingUsersPropertiesFile(File propertiesFile) throws IOException {
154
        propertiesFile.createNewFile();
155
        FileUtils.write(
156
                propertiesFile,
157
                "# Managing users properties file\n"
158
                + "#\n"
159
                + "# This file has been autogenerated by the cdmlib.\n"
160
                + "# In case the file is deleted the cdmlib will re-create it during the next start up.\n"
161
                + "#\n"
162
                + "# This is a java properties file to populate the InMemoryUserDetailsManager in any of \n"
163
                + "# the cdm-remote instances with special global management users which are granted to \n"
164
                + "# access special web services. Among these are the /manage/ web services and those\n"
165
                + "# triggering long running tasks. For more details please refer to\n"
166
                + "# https://dev.e-taxonomy.eu/redmine/projects/edit/wiki/CdmAuthorisationAndAccessControl\n"
167
                + "# \n"
168
                + "# Global management users have the role " + ROLE_MANAGE_CLIENT + ".\n"
169
                + "# and will be available in each of the cdm-remote instances.\n"
170
                + "# Changes made to this file are applied after restarting a cdm instance.\n"
171
                + "#\n"
172
                + "# This properties file should contain entries in the form\n"
173
                + "#    username=password\n"
174
                + "# -------------------------------------------------------------------------------------------\n"
175
                + "#\n"
176
                );
177
        }
178
}
(2-2/4)