1
1
package cz .muni .ics .oidc .server .filters ;
2
2
3
+ import cz .muni .ics .oidc .exceptions .ConfigurationException ;
4
+ import cz .muni .ics .oidc .saml .SamlProperties ;
3
5
import java .io .IOException ;
4
- import java .security .Principal ;
5
6
import java .util .Arrays ;
7
+ import java .util .Collections ;
6
8
import java .util .HashSet ;
9
+ import java .util .List ;
7
10
import java .util .Set ;
8
11
import javax .servlet .http .HttpServletRequest ;
9
12
import javax .servlet .http .HttpServletResponse ;
10
13
import javax .servlet .http .HttpSession ;
14
+ import lombok .Getter ;
11
15
import lombok .extern .slf4j .Slf4j ;
12
16
13
17
/**
14
- * Abstract class for Perun filters. All filters called in CallPerunFiltersFilter has to extend this.
15
- *
16
- * Configuration of filter names:
17
- * <ul>
18
- * <li><b>filter.names</b> - comma separated list of names of the request filters</li>
19
- * </ul>
18
+ * Abstract class for Perun AuthProc filters. All filters defined and called in the
19
+ * {@link cz.muni.ics.oidc.server.filters.AuthProcFiltersContainer} instance have to extend this base class.
20
20
*
21
21
* Configuration of filter (replace [name] part with the name defined for the filter):
22
22
* <ul>
23
23
* <li><b>filter.[name].class</b> - Class the filter instantiates</li>
24
- * <li><b>filter.[name].subs</b> - comma separated list of sub values for which execution of filter will be skipped
25
- * if user's SUB is in the list</li>
26
- * <li><b>filter.[name].clientIds</b> - comma separated list of client_id values for which execution of filter
27
- * will be skipped if client_id is in the list</li>
24
+ * <li><b>filter.[name].skip_for_users</b> - comma separated list of users for whom the execution of the filter
25
+ * will be skipped if the users' SUB matches any value in the list</li>
26
+ * <li><b>filter.[name].skip_for_clients</b> - comma separated list of clients for which the execution of the filter
27
+ * will be skipped if the CLIENT_ID matches any value in the list</li>
28
+ * <li><b>filter.[name].execute_for_users</b> - comma separated list of users for whom the filter will be executed
29
+ * if the users' SUB matches any value in the list</li>
30
+ * <li><b>filter.[name].execute_for_clients</b> - comma separated list of clients for whom the filter will be executed
31
+ * if the CLIENT_ID matches any value in the list</li>
28
32
* </ul>
33
+ * <i>NOTE: if none of the SKIP/EXECUTE conditions is specified (or the lists are empty), filter is run for all users
34
+ * and all clients</i>
29
35
*
30
36
* @see cz.muni.ics.oidc.server.filters.impl package for specific filters and their configuration
31
37
*
32
38
* @author Dominik Baranek <[email protected] >
33
39
* @author Dominik Frantisek Bucik <[email protected] >
34
40
*/
35
41
@ Slf4j
42
+ @ Getter
36
43
public abstract class AuthProcFilter {
37
44
45
+ public static final String APPLIED = "APPLIED_" ;
46
+
38
47
private static final String DELIMITER = "," ;
39
- private static final String CLIENT_IDS = "clientIds" ;
48
+ private static final String EXECUTE = "execute" ;
49
+ private static final String EXECUTE_FOR_CLIENTS = "execute_for_clients" ;
50
+ private static final String EXECUTE_FOR_USERS = "execute_for_users" ;
51
+ private static final String SKIP_FOR_CLIENTS = "skip_for_clients" ;
52
+ private static final String SKIP_FOR_USERS = "skip_for_users" ;
40
53
private static final String SUBS = "subs" ;
54
+ private static final String CLIENT_IDS = "clientIds" ;
41
55
42
56
private final String filterName ;
43
- private Set <String > clientIds = new HashSet <>();
44
- private Set <String > subs = new HashSet <>();
45
-
46
- public AuthProcFilter (AuthProcFilterParams params ) {
47
- filterName = params .getFilterName ();
48
-
49
- if (params .hasProperty (CLIENT_IDS )) {
50
- this .clientIds = new HashSet <>(Arrays .asList (params .getProperty (CLIENT_IDS ).split (DELIMITER )));
57
+ private final Set <String > executeForClients = new HashSet <>();
58
+ private final Set <String > executeForUsers = new HashSet <>();
59
+ private final Set <String > skipForClients = new HashSet <>();
60
+ private final Set <String > skipForUsers = new HashSet <>();
61
+
62
+ private final SamlProperties samlProperties ;
63
+
64
+ public AuthProcFilter (AuthProcFilterInitContext ctx ) throws ConfigurationException {
65
+ filterName = ctx .getFilterName ();
66
+ this .samlProperties = ctx .getBeanUtil ().getBean (SamlProperties .class );
67
+ initializeExecutionRulesLists (ctx );
68
+
69
+ if (!Collections .disjoint (executeForClients , skipForClients )) {
70
+ throw new ConfigurationException ("Filter '" + filterName + "' is configured to be run and skipped for the same client" );
71
+ } else if (!Collections .disjoint (executeForUsers , skipForUsers )) {
72
+ throw new ConfigurationException ("Filter '" + filterName + "' is configured to be run and skipped for the same user" );
51
73
}
52
74
53
- if (params .hasProperty (SUBS )) {
54
- this .subs = new HashSet <>(Arrays .asList (params .getProperty (SUBS ).split (DELIMITER )));
75
+ log .info ("{} - filter initialized" , filterName );
76
+ if (!skipForUsers .isEmpty ()) {
77
+ log .info ("{} - skip execution for users with SUB in: '{}'" , filterName , skipForUsers );
78
+ }
79
+ if (!skipForClients .isEmpty ()) {
80
+ log .info ("{} - skip execution for clients with CLIENT_ID in: '{}'" , filterName , skipForClients );
81
+ }
82
+ if (!executeForUsers .isEmpty ()) {
83
+ log .info ("{} - execute for users with SUB in: '{}'" , filterName , executeForUsers );
84
+ }
85
+ if (!executeForClients .isEmpty ()) {
86
+ log .info ("{} - execute for clients with CLIENT_ID in: '{}'" , filterName , executeForClients );
55
87
}
56
-
57
- log .debug ("{} - filter initialized" , filterName );
58
- log .debug ("{} - skip execution for users with SUB in: {}" , filterName , subs );
59
- log .debug ("{} - skip execution for clients with CLIENT_ID in: {}" , filterName , clientIds );
60
88
}
61
89
62
- protected abstract String getSessionAppliedParamName ();
90
+ protected String getSessionAppliedParamName () {
91
+ return APPLIED + getClass ().getSimpleName () + '_' + getFilterName ();
92
+ }
63
93
64
94
/**
65
95
* In this method is done whole logic of filer
@@ -69,10 +99,10 @@ public AuthProcFilter(AuthProcFilterParams params) {
69
99
* @return boolean if filter was successfully done
70
100
* @throws IOException this exception could be thrown because of failed or interrupted I/O operation
71
101
*/
72
- protected abstract boolean process (HttpServletRequest request , HttpServletResponse response , FilterParams params )
102
+ protected abstract boolean process (HttpServletRequest request , HttpServletResponse response , AuthProcFilterCommonVars params )
73
103
throws IOException ;
74
104
75
- public boolean doFilter (HttpServletRequest req , HttpServletResponse res , FilterParams params ) throws IOException {
105
+ public boolean doFilter (HttpServletRequest req , HttpServletResponse res , AuthProcFilterCommonVars params ) throws IOException {
76
106
if (!skip (req )) {
77
107
log .trace ("{} - executing filter" , filterName );
78
108
return process (req , res , params );
@@ -81,14 +111,18 @@ public boolean doFilter(HttpServletRequest req, HttpServletResponse res, FilterP
81
111
}
82
112
}
83
113
84
- private boolean skip (HttpServletRequest request ) {
85
- if (hasBeenApplied (request .getSession (true ))) {
114
+ private boolean skip (HttpServletRequest req ) {
115
+ if (hasBeenApplied (req .getSession (true ))) {
86
116
return true ;
87
117
}
88
118
log .debug ("{} - marking filter as applied" , filterName );
89
- request .getSession (true ).setAttribute (getSessionAppliedParamName (), true );
90
- return skipForSub (request .getUserPrincipal ())
91
- || skipForClientId (request .getParameter (PerunFilterConstants .PARAM_CLIENT_ID ));
119
+ req .getSession (true ).setAttribute (getSessionAppliedParamName (), true );
120
+ String sub = FiltersUtils .getUserIdentifier (req , samlProperties .getUserIdentifierAttribute ());
121
+ String clientId = FiltersUtils .getClientId (req );
122
+
123
+ boolean explicitExecution = executeForSub (sub ) || executeForClientId (clientId );
124
+ boolean explicitSkip = skipForClientId (clientId ) || skipForSub (sub );
125
+ return !explicitExecution && explicitSkip ;
92
126
}
93
127
94
128
private boolean hasBeenApplied (HttpSession sess ) {
@@ -100,21 +134,45 @@ private boolean hasBeenApplied(HttpSession sess) {
100
134
return false ;
101
135
}
102
136
103
- private boolean skipForSub (Principal p ) {
104
- String sub = (p != null ) ? p .getName () : null ;
105
- if (sub != null && subs .contains (sub )) {
106
- log .debug ("{} - skip filter execution: matched one of the ignored SUBS ({})" , filterName , sub );
107
- return true ;
108
- }
109
- return false ;
137
+ private boolean executeForSub (String sub ) {
138
+ return checkRule (sub , executeForUsers , "{} - execute filter: matched one of the explicit SUBS ({})" );
139
+ }
140
+
141
+ private boolean executeForClientId (String clientId ) {
142
+ return checkRule (clientId , executeForClients , "{} - execute filter: matched one of the explicit CLIENT_IDS ({})" );
143
+ }
144
+
145
+ private boolean skipForSub (String sub ) {
146
+ return checkRule (sub , skipForUsers , "{} - skip filter execution: matched one of the ignored SUBS ({})" );
110
147
}
111
148
112
149
private boolean skipForClientId (String clientId ) {
113
- if (clientId != null && clientIds .contains (clientId )){
114
- log .debug ("{} - skip filter execution: matched one of the ignored CLIENT_IDS ({})" , filterName , clientId );
150
+ return checkRule (clientId , skipForClients , "{} - skip filter execution: matched one of the ignored CLIENT_IDS ({})" );
151
+ }
152
+
153
+ private boolean checkRule (String param , Set <String > ruleSet , String logMsg ) {
154
+ if (param != null && ruleSet .contains (param )){
155
+ log .debug (logMsg , filterName , param );
115
156
return true ;
116
157
}
117
158
return false ;
118
159
}
119
160
161
+ private void initializeExecutionRulesLists (AuthProcFilterInitContext ctx ) {
162
+ initializeExecutionRuleList (ctx , EXECUTE_FOR_CLIENTS , executeForClients );
163
+ initializeExecutionRuleList (ctx , SKIP_FOR_CLIENTS , skipForClients );
164
+ initializeExecutionRuleList (ctx , CLIENT_IDS , skipForClients );
165
+
166
+ initializeExecutionRuleList (ctx , EXECUTE_FOR_USERS , executeForUsers );
167
+ initializeExecutionRuleList (ctx , SKIP_FOR_USERS , skipForUsers );
168
+ initializeExecutionRuleList (ctx , SUBS , skipForUsers );
169
+ }
170
+
171
+ private void initializeExecutionRuleList (AuthProcFilterInitContext ctx , String property , Set <String > list ) {
172
+ if (ctx .hasProperty (property )) {
173
+ String value = ctx .getProperty (property , "" );
174
+ list .addAll (Arrays .asList (value .split (DELIMITER )));
175
+ }
176
+ }
177
+
120
178
}
0 commit comments