Project

General

Profile

Download (7.21 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.nio.charset.Charset;
15
import java.util.Properties;
16

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

    
29
import eu.etaxonomy.cdm.config.ConfigFileUtil;
30

    
31
/**
32
 *
33
 * <b>NOTE</b> on nested @Configuration classes:
34
 *
35
 * When bootstrapping such an arrangement, only the outer class need be registered against the application context.
36
 * By virtue of being a nested @Configuration class, DatabaseConfig will be registered automatically. This avoids
37
 * the need to use an @Import annotation when the relationship between AppConfig DatabaseConfig is already implicitly
38
 * clear.
39
 *
40
 * @author a.kohlbecker
41
 * @since Oct 6, 2016
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
    @Autowired
54
    private ConfigFileUtil configFileUtil;
55

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

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

    
102
    /**
103
     * Allow anonymous authentication for all other services.
104
     *
105
     * <b>NOTE:</b> Further access restrictions are defined
106
     * in the OAuth2ServerConfiguration.
107
     *
108
     * @author a.kohlbecker
109
     * @since Oct 6, 2016
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.perUserCdmFolder(), 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
    private void makeManagingUsersPropertiesFile(File propertiesFile) throws IOException {
150
        propertiesFile.createNewFile();
151
        FileUtils.write(
152
                propertiesFile,
153
                "# Managing users properties file\n"
154
                + "#\n"
155
                + "# This file has been autogenerated by the cdmlib.\n"
156
                + "# In case the file is deleted the cdmlib will re-create it during the next start up.\n"
157
                + "#\n"
158
                + "# This is a java properties file to populate the InMemoryUserDetailsManager in any of \n"
159
                + "# the cdm-remote instances with special global management users which are granted to \n"
160
                + "# access special web services. Among these are the /manage/ web services and those\n"
161
                + "# triggering long running tasks. For more details please refer to\n"
162
                + "# https://dev.e-taxonomy.eu/redmine/projects/edit/wiki/CdmAuthorisationAndAccessControl\n"
163
                + "# \n"
164
                + "# Global management users have the role " + ROLE_MANAGE_CLIENT + ".\n"
165
                + "# and will be available in each of the cdm-remote instances.\n"
166
                + "# Changes made to this file are applied after restarting a cdm instance.\n"
167
                + "#\n"
168
                + "# This properties file should contain entries in the form\n"
169
                + "#    username=password\n"
170
                + "# -------------------------------------------------------------------------------------------\n"
171
                + "#\n",
172
                Charset.defaultCharset()
173
                );
174
        }
175
}
(3-3/5)