├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── README.md
├── pom.xml
├── src
├── main
│ ├── assemblies
│ │ └── plugin.xml
│ ├── java
│ │ └── org
│ │ │ └── elasticsearch
│ │ │ └── plugins
│ │ │ └── security
│ │ │ ├── MalformedConfigurationException.java
│ │ │ ├── SecurityPlugin.java
│ │ │ ├── filter
│ │ │ ├── ActionPathFilter.java
│ │ │ ├── DlsWriteFilter.java
│ │ │ ├── PermDlsEvaluator.java
│ │ │ ├── PermLevel.java
│ │ │ ├── PermLevelEvaluator.java
│ │ │ └── SecureRestFilter.java
│ │ │ ├── http
│ │ │ ├── realm
│ │ │ │ ├── AllPermsRealm.java
│ │ │ │ └── LdapTlsContextFactory.java
│ │ │ └── tomcat
│ │ │ │ ├── ExtendedJndiRealm.java
│ │ │ │ ├── ExtendedSpnegoAuthenticator.java
│ │ │ │ ├── ExtendedTomcat.java
│ │ │ │ ├── TomcatHttpServerRestChannel.java
│ │ │ │ ├── TomcatHttpServerRestRequest.java
│ │ │ │ ├── TomcatHttpServerTransport.java
│ │ │ │ ├── TomcatHttpServerTransportModule.java
│ │ │ │ ├── TomcatHttpTransportHandlerServlet.java
│ │ │ │ └── TomcatUserRoleCallback.java
│ │ │ ├── service
│ │ │ ├── SecurityService.java
│ │ │ └── permission
│ │ │ │ ├── DlsPermission.java
│ │ │ │ ├── PermEvaluator.java
│ │ │ │ └── UserRoleCallback.java
│ │ │ └── util
│ │ │ ├── EditableRestRequest.java
│ │ │ └── SecurityUtil.java
│ └── resources
│ │ └── es-plugin.properties
└── test
│ ├── java
│ └── org
│ │ └── elasticsearch
│ │ └── plugins
│ │ └── security
│ │ ├── AbstractUnitTest.java
│ │ ├── SpnegoAdTests.java
│ │ ├── SpnegoAdTestsAlternateLdapUrl.java
│ │ ├── SpnegoTests.java
│ │ ├── SpnegoWaffleTests.java
│ │ ├── SslSpnegoAdTests.java
│ │ ├── filter
│ │ ├── AbstractPermTests.java
│ │ ├── DlsTests.java
│ │ └── SecurityPermTests.java
│ │ └── waffle
│ │ └── TestProvider.java
│ └── resources
│ ├── dls_allow_emptyarray.json
│ ├── dls_default_test_allowall.json
│ ├── dls_default_test_denyall.json
│ ├── dls_denyall_emptyarray.json
│ ├── dls_dummy_content.json
│ ├── dls_dummy_content_updt.json
│ ├── dls_dummy_content_without_dls.json
│ ├── dls_field_query.json
│ ├── dls_test_normal.json
│ ├── dummy_content.json
│ ├── hnelsonclient.p12
│ ├── issues
│ ├── dls1
│ │ ├── default.json
│ │ └── rules.json
│ └── dls2
│ │ ├── data.json
│ │ ├── default.json
│ │ ├── expected.json
│ │ └── rules.json
│ ├── krb5.conf
│ ├── krb5_utest.keytab
│ ├── localhost_tc.p12
│ ├── log4j.properties
│ ├── login.conf
│ ├── non_field_query.json
│ ├── test_bad_format.json
│ ├── test_default.json
│ ├── test_denyall.json
│ ├── test_denyall_emptyarray.json
│ ├── test_facet_search.json
│ ├── test_malformed_structure.json
│ ├── test_multiple_wildcard_indices.json
│ ├── test_no_default.json
│ ├── test_normal.json
│ ├── test_normal_fqn.json
│ ├── test_normal_indices.json
│ ├── test_normal_withuserroletypes.json
│ ├── test_wildcard.json
│ ├── test_wildcard_fqn.json
│ ├── test_wildcard_indices.json
│ ├── test_wildcard_indices2.json
│ ├── truststore.jks
│ ├── ur_test_all.json
│ ├── ur_test_duplicate.json
│ └── ur_test_normal.json
└── travisscripts
└── travis-before-install.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | test-output/
3 |
4 | /build.gradle
5 | *.log
6 | .externalToolBuilders
7 | maven-eclipse.xml
8 |
9 | ## eclipse ignores (use 'mvn eclipse:eclipse' to build eclipse projects)
10 | ## The only configuration files which are not ignored are certain files in
11 | ## .settings (as listed below) since these files ensure common coding
12 | ## style across Eclipse and IDEA.
13 | ## Other files (.project, .classpath) should be generated through Maven which
14 | ## will correctly set the classpath based on the declared dependencies.
15 | .project
16 | .classpath
17 | eclipse-build
18 | */.project
19 | */.classpath
20 | */eclipse-build
21 | /.settings/
22 | !/.settings/org.eclipse.core.resources.prefs
23 | !/.settings/org.eclipse.jdt.core.prefs
24 | !/.settings/org.eclipse.jdt.ui.prefs
25 | !/.settings/org.eclipse.jdt.groovy.core.prefs
26 | bin
27 | tomcat.*
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - openjdk7
5 | - oraclejdk7
6 |
7 | before_install:
8 | - sudo chmod -R 777 ./travisscripts/travis-before-install.sh
9 | - sudo ./travisscripts/travis-before-install.sh
10 |
11 | install: mvn clean install -Dgpg.skip=true
12 |
13 | notifications:
14 | email:
15 | recipients:
16 | - hendrikdev22@gmail.com
17 | on_success: always
18 | on_failure: always
19 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2013-2014 Hendrik Saly
2 |
3 | Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions)
4 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or
5 | conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
6 | appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
7 |
8 | Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
9 | required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to
10 | You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of
11 | this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage,
12 | computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the
13 | possibility of such damages.
14 |
15 | Licensed under the "No License" license (github default license):
16 | http://choosealicense.com/licenses/no-license/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # News/Status
2 | This plugin is no longer maintained, if you're looking for security for elasticsearch i recommend
3 |
4 | * [Search Guard](https://github.com/floragunncom/search-guard) - Free (and open source) plugin from [floragunn GmbH](https://floragunn.com/searchguard/), supports Elasticsearch 5 as well as Elasticsearch 6
5 |
6 | ## elasticsearch-security-plugin (Unmaintained)
7 | ### This plugin is to be considered as insecure, do not use it because its unmaintained
8 | 
9 |
10 | Documentation removed.
11 |
12 |
License
13 | Copyright 2013-2014 Hendrik Saly
14 |
15 | Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions)
16 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or
17 | conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
18 | appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
19 |
20 | Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
21 | required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to
22 | You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of
23 | this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage,
24 | computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the
25 | possibility of such damages.
26 |
27 | Licensed under the "No License" license (github default):
28 | http://choosealicense.com/licenses/no-license/
29 |
30 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | 3.1.0
7 |
8 |
9 | com.github.salyh.elasticsearch
10 | elasticsearch-security-plugin
11 | 0.0.2.Beta9-ea1.4
12 | jar
13 |
14 | elasticsearch-security-plugin
15 | Provide security related features for elasticsearch
16 | https://github.com/salyh/elasticsearch-security-plugin
17 | 2013
18 |
19 |
20 |
21 | No License license - Copyright 2013-2014 Hendrik Saly
22 | http://choosealicense.com/licenses/no-license
23 | manual
24 | Copyright 2013-2014 Hendrik Saly
25 |
26 |
27 |
28 |
29 |
30 | bintray-salyh-maven-elasticsearch-river-imap
31 | salyh-maven-elasticsearch-river-imap
32 | https://api.bintray.com/maven/salyh/maven/elasticsearch-security-plugin
33 |
34 |
35 |
36 |
37 | 1.4.1
38 | 7.0.54
39 | 2.0.0-M16
40 | \\
41 |
42 |
43 |
44 | https://github.com/salyh/elasticsearch-security-plugin
45 | scm:git:git@github.com:salyh/elasticsearch-security-plugin.git
46 | scm:git:git@github.com:salyh/elasticsearch-security-plugin.git
47 |
48 |
49 |
50 | GitHub
51 | https://github.com/salyh/elasticsearch-security-plugin/issues
52 |
53 |
54 |
55 |
56 | hendrikdev22@gmail.com
57 | Hendrik Saly
58 | https://github.com/salyh
59 | salyh
60 |
61 |
62 |
63 |
64 |
65 | Ram Kotamaraja
66 | https://github.com/rkotamaraja
67 |
68 |
69 |
70 |
71 |
72 | org.sonatype.oss
73 | oss-parent
74 | 7
75 |
76 |
77 |
78 |
79 |
80 | junit
81 | junit
82 | 4.11
83 | test
84 |
85 |
86 |
87 | commons-io
88 | commons-io
89 | 2.4
90 | test
91 |
92 |
93 |
94 | io.searchbox
95 | jest
96 | 0.1.2
97 | test
98 |
99 |
100 |
101 | com.github.tlrx
102 | elasticsearch-test
103 | 1.2.1
104 | test
105 |
106 |
107 |
108 | org.elasticsearch
109 | elasticsearch
110 | ${elasticsearch.version}
111 |
112 |
113 |
114 | log4j
115 | log4j
116 | 1.2.17
117 |
118 |
119 |
120 |
121 | org.slf4j
122 | slf4j-api
123 | 1.7.7
124 | test
125 | true
126 |
127 |
128 |
129 | org.slf4j
130 | slf4j-log4j12
131 | 1.7.7
132 | test
133 | true
134 |
135 |
136 |
137 | org.apache.httpcomponents
138 | httpclient
139 | 4.3.2
140 | test
141 |
142 |
143 |
144 | org.apache.httpcomponents
145 | fluent-hc
146 | 4.3.2
147 | test
148 |
149 |
150 |
151 | org.apache.httpcomponents
152 | httpcore
153 | 4.3.2
154 | test
155 |
156 |
157 |
158 | org.apache.tomcat.embed
159 | tomcat-embed-core
160 | ${tomcat.version}
161 |
162 |
163 |
164 | org.apache.tomcat.embed
165 | tomcat-embed-logging-log4j
166 | ${tomcat.version}
167 |
168 |
169 |
170 | org.apache.tomcat
171 | tomcat-jsp-api
172 | ${tomcat.version}
173 |
174 |
175 |
176 | com.github.dblock.waffle
177 | waffle-tomcat7
178 | 1.6
179 |
180 |
181 |
182 | com.github.dblock.waffle
183 | waffle-tests
184 | 1.6
185 |
186 |
187 |
188 |
189 | com.jayway.jsonpath
190 | json-path
191 | 0.9.1
192 |
193 |
194 |
195 | com.jayway.jsonpath
196 | json-path-assert
197 | 0.9.1
198 | test
199 |
200 |
201 |
202 | net.sourceforge.spnego
203 | spnego
204 | 7.0
205 | test
206 |
207 |
208 |
209 |
210 |
211 | org.apache.directory.server
212 | apacheds-all
213 | ${apache.ds.version}
214 |
215 |
217 |
218 | org.apache.directory.shared
219 | shared-ldap-schema
220 |
221 |
222 | org.apache.directory.api
223 | api-ldap-schema-data
224 |
225 |
226 |
227 |
228 |
229 | org.apache.directory.server
230 | kerberos-client
231 | ${apache.ds.version}
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 | ${basedir}/src/test/java
241 |
242 | **/*.json
243 | **/*.yml
244 |
245 |
246 |
247 | ${basedir}/src/test/resources
248 | false
249 |
250 | **/*.*
251 |
252 |
253 | login.conf
254 |
255 |
256 |
257 |
258 | ${basedir}/src/test/resources
259 | true
260 |
261 | login.conf
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 | org.apache.maven.plugins
272 | maven-enforcer-plugin
273 | 1.3.1
274 |
275 |
276 | enforce-java
277 |
278 | enforce
279 |
280 |
281 |
282 |
283 | 1.7
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | org.apache.maven.plugins
292 | maven-jar-plugin
293 | 2.5
294 |
295 | true
296 |
297 |
298 |
299 | true
300 | true
301 |
302 |
303 |
304 |
305 |
306 | org.apache.maven.plugins
307 | maven-compiler-plugin
308 | 3.1
309 |
310 | 1.7
311 | 1.7
312 |
313 |
314 |
315 | org.apache.maven.plugins
316 | maven-surefire-plugin
317 | 2.17
318 |
319 |
320 | **/*Test*.java
321 |
322 |
323 |
324 |
325 | org.apache.maven.plugins
326 | maven-source-plugin
327 | 2.3
328 |
329 |
330 | attach-sources
331 |
332 | jar
333 |
334 |
335 |
336 |
337 |
338 | maven-assembly-plugin
339 | 2.4
340 |
341 | false
342 | ${project.build.directory}/releases/
343 |
344 | ${basedir}/src/main/assemblies/plugin.xml
345 |
346 |
347 |
348 |
349 | package
350 |
351 | single
352 |
353 |
354 |
355 |
356 |
357 | org.apache.maven.plugins
358 | maven-gpg-plugin
359 | 1.5
360 |
361 |
362 | sign-artifacts
363 | verify
364 |
365 | sign
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 | sonatype-releases
376 | Sonatype Releases Repository
377 | http://oss.sonatype.org/content/repositories/releases
378 |
379 |
380 |
381 |
382 | jspresso
383 | http://repository.jspresso.org/maven2/
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 | unix
392 |
393 |
394 | unix
395 |
396 |
397 |
398 |
399 |
400 | org.apache.maven.plugins
401 | maven-surefire-plugin
402 |
403 |
404 | **/*affle*.java
405 |
406 |
407 |
408 |
409 |
410 |
411 | /
412 |
413 |
414 |
415 |
416 |
--------------------------------------------------------------------------------
/src/main/assemblies/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | plugin
4 |
5 | zip
6 |
7 | false
8 |
9 |
10 | /
11 | true
12 | true
13 |
14 | org.elasticsearch:elasticsearch
15 |
16 |
17 |
18 |
19 |
20 | org.elasticsearch:elasticsearch-security-plugin
21 |
22 |
23 |
24 |
25 |
26 | _site
27 | src/site
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/MalformedConfigurationException.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | public class MalformedConfigurationException extends Exception {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public MalformedConfigurationException(final String message) {
8 | super(message);
9 |
10 | }
11 |
12 | public MalformedConfigurationException(final Throwable cause) {
13 | super(cause);
14 |
15 | }
16 |
17 | public MalformedConfigurationException(final String message,
18 | final Throwable cause) {
19 | super(message, cause);
20 |
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/SecurityPlugin.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import java.util.Collection;
4 |
5 | import org.elasticsearch.common.collect.Lists;
6 | import org.elasticsearch.common.component.LifecycleComponent;
7 | import org.elasticsearch.common.logging.ESLogger;
8 | import org.elasticsearch.common.logging.Loggers;
9 | import org.elasticsearch.plugins.AbstractPlugin;
10 | import org.elasticsearch.plugins.security.service.SecurityService;
11 |
12 | public class SecurityPlugin extends AbstractPlugin {
13 |
14 | private final ESLogger log = Loggers.getLogger(this.getClass());
15 |
16 | public SecurityPlugin() {
17 | log.debug("Starting Security Plugin");
18 | }
19 |
20 | @SuppressWarnings("rawtypes")
21 | @Override
22 | public Collection> services() {
23 | final Collection> services = Lists
24 | .newArrayList();
25 |
26 | services.add(SecurityService.class);
27 |
28 | return services;
29 | }
30 |
31 | @Override
32 | public String description() {
33 | return "Security Plugin";
34 | }
35 |
36 | @Override
37 | public String name() {
38 | return "elasticsearch-security-plugin";
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/ActionPathFilter.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Iterator;
6 | import java.util.List;
7 |
8 | import org.elasticsearch.common.bytes.BytesArray;
9 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
10 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestChannel;
11 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestRequest;
12 | import org.elasticsearch.plugins.security.http.tomcat.TomcatUserRoleCallback;
13 | import org.elasticsearch.plugins.security.service.SecurityService;
14 | import org.elasticsearch.plugins.security.util.EditableRestRequest;
15 | import org.elasticsearch.plugins.security.util.SecurityUtil;
16 | import org.elasticsearch.rest.RestFilterChain;
17 | import org.elasticsearch.rest.RestStatus;
18 |
19 | public class ActionPathFilter extends SecureRestFilter {
20 |
21 | public ActionPathFilter(final SecurityService securityService) {
22 | super(securityService);
23 |
24 | }
25 |
26 | @Override
27 | public void processSecure(final TomcatHttpServerRestRequest request,
28 | final TomcatHttpServerRestChannel channel,
29 | final RestFilterChain filterChain) {
30 |
31 | if (SecurityUtil.stringContainsItemFromListAsTypeOrIndex(
32 | request.path(), SecurityUtil.BUILT_IN_ADMIN_COMMANDS)) {
33 | log.warn("Index- or Typename should not contains admin commands like "
34 | + Arrays.toString(SecurityUtil.BUILT_IN_ADMIN_COMMANDS));
35 | }
36 |
37 | if (SecurityUtil.stringContainsItemFromListAsTypeOrIndex(
38 | request.path(), securityService.isStrictModeEnabled()?SecurityUtil.BUILT_IN_READ_COMMANDS_STRICT : SecurityUtil.BUILT_IN_READ_COMMANDS_LAX)) {
39 | log.warn("Index- or Typename should not contains search commands like "
40 | + Arrays.toString(securityService.isStrictModeEnabled()?SecurityUtil.BUILT_IN_READ_COMMANDS_STRICT : SecurityUtil.BUILT_IN_READ_COMMANDS_LAX));
41 | }
42 |
43 | if (SecurityUtil.stringContainsItemFromListAsTypeOrIndex(
44 | request.path(), securityService.isStrictModeEnabled()?SecurityUtil.BUILT_IN_WRITE_COMMANDS_STRICT : SecurityUtil.BUILT_IN_WRITE_COMMANDS_LAX)) {
45 | log.warn("Index- or Typename should not contains write commands like "
46 | + Arrays.toString(securityService.isStrictModeEnabled()?SecurityUtil.BUILT_IN_WRITE_COMMANDS_STRICT : SecurityUtil.BUILT_IN_WRITE_COMMANDS_LAX));
47 | }
48 |
49 | try {
50 |
51 | final PermLevel permLevel = new PermLevelEvaluator(
52 | securityService.getXContentSecurityConfiguration(
53 | getType(), getId()))
54 | .evaluatePerm(
55 | SecurityUtil.getIndices(request),
56 | SecurityUtil.getTypes(request),
57 | getClientHostAddress(request),
58 | new TomcatUserRoleCallback(request
59 | .getHttpServletRequest(),securityService.getSettings().get("security.ssl.userattribute")));
60 |
61 | if (permLevel == PermLevel.NONE) {
62 | SecurityUtil.send(request, channel, RestStatus.FORBIDDEN,
63 | "No permission (at all)");
64 | return;
65 | }
66 |
67 | if (permLevel.ordinal() < PermLevel.ALL.ordinal()
68 | && SecurityUtil.isAdminRequest(request)) {
69 | SecurityUtil.send(request, channel, RestStatus.FORBIDDEN,
70 | "No permission (for admin actions)");
71 | return;
72 | }
73 |
74 | if (permLevel.ordinal() < PermLevel.READWRITE.ordinal()
75 | && SecurityUtil.isWriteRequest(request,securityService.isStrictModeEnabled())) {
76 | SecurityUtil.send(request, channel, RestStatus.FORBIDDEN,
77 | "No permission (for write actions)");
78 | return;
79 | }
80 |
81 | if (permLevel == PermLevel.READONLY
82 | && !SecurityUtil.isReadRequest(request,securityService.isStrictModeEnabled())) {
83 | SecurityUtil.send(request, channel, RestStatus.FORBIDDEN,
84 | "No permission (for read actions)");
85 | return;
86 | }
87 |
88 | // Ram Kotamarja - START
89 | // adding code to modify request modification before it hits elastic
90 | // search to apply the search filters
91 | modifiyKibanaRequest(request, channel);
92 | // Ram Kotamaraja - END
93 |
94 |
95 | filterChain.continueProcessing(request, channel);
96 | return;
97 | } catch (final MalformedConfigurationException e) {
98 | log.error("Cannot parse security configuration ", e);
99 | SecurityUtil.send(request, channel,
100 | RestStatus.INTERNAL_SERVER_ERROR,
101 | "Cannot parse security configuration");
102 |
103 | return;
104 | } catch (final Exception e) {
105 | log.error("Generic error: ", e);
106 | SecurityUtil.send(request, channel,
107 | RestStatus.INTERNAL_SERVER_ERROR,
108 | "Generic error, see log for details");
109 |
110 | return;
111 | }
112 |
113 | }
114 |
115 | /**
116 | * Method added to modify the request on the fly to
117 | * allow it to process generic queries coming from kibana by
118 | * validating against the security framework (contributed by Ram Kotamaraja)
119 | * @param request
120 | */
121 | private void modifiyKibanaRequest(
122 | final TomcatHttpServerRestRequest request,
123 | final TomcatHttpServerRestChannel channel) {
124 |
125 | List reqTypesList = SecurityUtil.getTypes(request);
126 | if (reqTypesList != null && !reqTypesList.isEmpty()
127 | && reqTypesList.size() > 0) {
128 | // This means, there is a type specified in the request and so there
129 | // is not need to do anything as the framework will take care of the
130 | // type level security
131 | log.debug("Not modifying the request (for kibana) as there is one or more types already associated with the request");
132 | reqTypesList = null;
133 | return;
134 | }
135 |
136 | String kibanaPermLevel = null;
137 | try {
138 | kibanaPermLevel = securityService.getXContentSecurityConfiguration(
139 | getType(), getKibanaId());
140 | } catch (Exception e) {
141 | log.debug("No Kibana configuration found, so continuing the rest of the process: "+e.getMessage());
142 | return;
143 | }
144 |
145 | List kibanaTypesList = null;
146 | List authorizedTypesList = new ArrayList();
147 | try {
148 | if (kibanaPermLevel != null && kibanaPermLevel.length() > 0) {
149 | kibanaTypesList = securityService.getKibanaTypes(SecurityUtil
150 | .getIndices(request));
151 | }
152 |
153 | final String reqContent = request.content().toUtf8();
154 | String modifiedContent = reqContent;
155 |
156 | // checking where the original request has any types
157 | List requestTypes = SecurityUtil.getTypes(request);
158 |
159 | // If original request has any requests, then skip the logic below
160 | // as
161 | // permission evaluation has to be done based on that specific type
162 | if (requestTypes == null || requestTypes.isEmpty()
163 | || requestTypes.size() == 0) {
164 | if (kibanaTypesList != null) {
165 |
166 | // determine authorized types list
167 |
168 |
169 | Iterator kibanaTypesItr = kibanaTypesList
170 | .iterator();
171 |
172 | while (kibanaTypesItr.hasNext()) {
173 |
174 | List kibanaType = new ArrayList();
175 | kibanaType.add((String) kibanaTypesItr.next());
176 | final PermLevel permLevel = new PermLevelEvaluator(
177 | securityService
178 | .getXContentSecurityConfiguration(
179 | getType(), getId()))
180 | .evaluatePerm(
181 | SecurityUtil.getIndices(request),
182 | // SecurityUtil.getTypes(request),
183 | kibanaType,
184 | getClientHostAddress(request),
185 | new TomcatUserRoleCallback(
186 | request.getHttpServletRequest(),
187 | securityService
188 | .getSettings()
189 | .get("security.ssl.userattribute")));
190 |
191 | log.debug("Kibana perm level = "+permLevel);
192 |
193 | if (!permLevel.equals(PermLevel.NONE)) {
194 | authorizedTypesList.addAll(kibanaType);
195 | }
196 | }
197 |
198 |
199 |
200 | log.debug("Processing kibana types "+ kibanaTypesList);
201 | log.debug("request Content = "+ reqContent);
202 |
203 | String kibanaFilterStarter = "\"must\":[";
204 | int beginIndex = reqContent.indexOf(kibanaFilterStarter);
205 |
206 | if (beginIndex > 0) {
207 | String preReqContent = reqContent.substring(0,
208 | beginIndex + kibanaFilterStarter.length());
209 | String postReqContent = reqContent.substring(beginIndex
210 | + kibanaFilterStarter.length());
211 |
212 | modifiedContent = preReqContent
213 | + "{\"or\": {\"filters\":[";
214 |
215 | if (authorizedTypesList != null) {
216 | Iterator authorizedTypesItr = authorizedTypesList
217 | .iterator();
218 | while (authorizedTypesItr.hasNext()) {
219 | modifiedContent += "{\"type\":{\"value\":\""
220 | + authorizedTypesItr.next().toString()
221 | + "\"}},";
222 | }
223 | modifiedContent = modifiedContent.substring(0,
224 | modifiedContent.length() - 1);
225 | }
226 |
227 | modifiedContent += "]}}," + postReqContent;
228 | log.debug("modified request content = " + modifiedContent);
229 |
230 | request.setContent(new BytesArray(modifiedContent));
231 | request.setAttribute(TomcatHttpServerRestRequest.REQUEST_CONTENT_ATTRIBUTE, request.getContent());
232 |
233 | }
234 | }
235 | }
236 | } catch (MalformedConfigurationException e) {
237 | log.error("Cannot parse security configuration ", e);
238 | SecurityUtil.send(request, channel,
239 | RestStatus.INTERNAL_SERVER_ERROR,
240 | "Cannot parse security configuration");
241 |
242 | return;
243 | } catch (Exception e) {
244 | log.error("Generic error: ", e);
245 | SecurityUtil.send(request, channel,
246 | RestStatus.INTERNAL_SERVER_ERROR,
247 | "Generic error, see log for details");
248 |
249 | return;
250 | }
251 |
252 | }
253 |
254 | /**
255 | * Method to return the default id (contributed by Ram Kotamaraja)
256 | * @return String - default id string
257 | */
258 | protected String getKibanaId() {
259 | return "kibana";
260 | }
261 |
262 | @Override
263 | protected String getType() {
264 |
265 | return "actionpathfilter";
266 | }
267 |
268 | @Override
269 | protected String getId() {
270 |
271 | return "actionpathfilter";
272 | }
273 |
274 | }
275 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/DlsWriteFilter.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 |
7 | import org.elasticsearch.action.get.GetRequest;
8 | import org.elasticsearch.action.get.GetResponse;
9 | import org.elasticsearch.common.collect.Tuple;
10 | import org.elasticsearch.common.xcontent.XContentBuilder;
11 | import org.elasticsearch.common.xcontent.XContentFactory;
12 | import org.elasticsearch.common.xcontent.XContentHelper;
13 | import org.elasticsearch.common.xcontent.XContentType;
14 | import org.elasticsearch.common.xcontent.support.XContentMapValues;
15 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
16 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestChannel;
17 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestRequest;
18 | import org.elasticsearch.plugins.security.http.tomcat.TomcatUserRoleCallback;
19 | import org.elasticsearch.plugins.security.service.SecurityService;
20 | import org.elasticsearch.plugins.security.service.permission.DlsPermission;
21 | import org.elasticsearch.plugins.security.util.EditableRestRequest;
22 | import org.elasticsearch.plugins.security.util.SecurityUtil;
23 | import org.elasticsearch.rest.RestFilterChain;
24 | import org.elasticsearch.rest.RestStatus;
25 |
26 | /**
27 | * NOT USED YET Protecting documents/fields from being updated or deleted on
28 | * dlstoken basis
29 | *
30 | *
31 | */
32 | public class DlsWriteFilter extends SecureRestFilter {
33 |
34 | public DlsWriteFilter(final SecurityService securityService) {
35 | super(securityService);
36 |
37 | }
38 |
39 | @Override
40 | public void processSecure(final TomcatHttpServerRestRequest request,
41 | final TomcatHttpServerRestChannel channel,
42 | final RestFilterChain filterChain) {
43 |
44 | try {
45 |
46 | if (!SecurityUtil.isWriteRequest(request, securityService.isStrictModeEnabled())) {
47 | filterChain.continueProcessing(request, channel);
48 | return;
49 | }
50 |
51 | final List dlsTokens = new PermDlsEvaluator(
52 | securityService.getXContentSecurityConfiguration(
53 | getType(), getId()))
54 | .evaluatePerm(
55 | SecurityUtil.getIndices(request),
56 | SecurityUtil.getTypes(request),
57 | getClientHostAddress(request),
58 | new TomcatUserRoleCallback(request
59 | .getHttpServletRequest(),securityService.getSettings().get("security.ssl.userattribute")));
60 |
61 | final String json = XContentHelper.convertToJson(request.content(),
62 | true);
63 |
64 | // TODO _bulk api
65 |
66 | // final XContentParser parser = XContentHelper.createParser(request
67 | // .content());
68 |
69 | log.debug("fieldlevelpermfilter orig: " + json);
70 |
71 | log.debug("dls tokens: " + dlsTokens);
72 |
73 | final String id = SecurityUtil.getId(request);
74 |
75 | try {
76 | final GetResponse res = securityService
77 | .getClient()
78 | .get(new GetRequest(SecurityUtil.getIndices(request)
79 | .get(0), SecurityUtil.getTypes(request).get(0),
80 | id)).actionGet();
81 |
82 | log.debug("document with id found: " + res.getId());
83 |
84 | final List perms = securityService
85 | .parseDlsPermissions(res.getSourceAsBytesRef());
86 |
87 | log.debug("perms " + perms);
88 |
89 | final List fields = new ArrayList();
90 |
91 | for (final DlsPermission p : perms) {
92 |
93 | if (p.isAnyTokenAllowedToUpdate(dlsTokens))
94 |
95 | {
96 | fields.add(p.getField());
97 | }
98 |
99 | }
100 | log.debug("ffields " + fields);
101 |
102 | final Tuple> mapTuple = XContentHelper
103 | .convertToMap(request.content(), true);
104 |
105 | final Map filteredSource = XContentMapValues
106 | .filter(mapTuple.v2(), fields.toArray(new String[0]),
107 | new String[] { "*" });
108 |
109 | log.debug("filteredSource " + filteredSource);
110 |
111 | final XContentBuilder sourceToBeReturned = XContentFactory
112 | .contentBuilder(mapTuple.v1()).map(filteredSource);
113 |
114 | final EditableRestRequest err = new EditableRestRequest(request);
115 | err.setContent(sourceToBeReturned.bytes());
116 |
117 | filterChain.continueProcessing(err, channel);
118 | return;
119 |
120 | } catch (final Exception e) {
121 | // TODO Auto-generated catch block
122 | // e.printStackTrace();
123 | log.debug("no document with id found: " + e.getMessage());
124 | }
125 |
126 | filterChain.continueProcessing(request, channel);
127 | return;
128 | } catch (final MalformedConfigurationException e) {
129 | log.error("Cannot parse security configuration ", e);
130 | SecurityUtil.send(request, channel,
131 | RestStatus.INTERNAL_SERVER_ERROR,
132 | "Cannot parse security configuration");
133 |
134 | return;
135 | } catch (final Exception e) {
136 | log.error("Generic error: ", e);
137 | SecurityUtil.send(request, channel,
138 | RestStatus.INTERNAL_SERVER_ERROR,
139 | "Generic error, see log for details");
140 |
141 | return;
142 | }
143 |
144 | }
145 |
146 | @Override
147 | protected String getType() {
148 |
149 | return "dlspermissions";
150 | }
151 |
152 | @Override
153 | protected String getId() {
154 |
155 | return "dlspermissions";
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/PermDlsEvaluator.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.elasticsearch.plugins.security.service.permission.PermEvaluator;
7 |
8 |
9 | public class PermDlsEvaluator extends PermEvaluator> {
10 |
11 | public PermDlsEvaluator(final String xSecurityConfiguration) {
12 | super(xSecurityConfiguration);
13 |
14 | }
15 |
16 | @Override
17 | protected List createFromString(final String s) {
18 |
19 | final List fields = new ArrayList();
20 |
21 | if (s == null) {
22 | return fields;
23 | }
24 |
25 | final String[] split = s.split(",");
26 |
27 | for (int i = 0; i < split.length; i++) {
28 | fields.add(split[i]);
29 | }
30 |
31 | return fields;
32 |
33 | }
34 |
35 | @Override
36 | protected String getPermissionFieldName() {
37 | return "dlstoken";
38 | }
39 |
40 | @Override
41 | protected List getDefaultPermLevelForEvaluator() {
42 | return createFromString(null);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/PermLevel.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | public enum PermLevel {
4 | NONE, READONLY, READWRITE, ALL;
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/PermLevelEvaluator.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.util.List;
4 |
5 | import org.elasticsearch.plugins.security.service.permission.PermEvaluator;
6 |
7 | public class PermLevelEvaluator extends PermEvaluator {
8 |
9 | protected PermLevelEvaluator(final String xSecurityConfiguration) {
10 | super(xSecurityConfiguration);
11 |
12 | }
13 |
14 | @Override
15 | protected PermLevel createFromString(final String s) {
16 | return PermLevel.valueOf(s);
17 | }
18 |
19 | @Override
20 | protected String getPermissionFieldName() {
21 | return "permission";
22 | }
23 |
24 | @Override
25 | protected PermLevel getDefaultPermLevelForEvaluator() {
26 | return PermLevel.NONE;
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/filter/SecureRestFilter.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.net.InetAddress;
4 | import java.net.UnknownHostException;
5 | import java.util.List;
6 |
7 | import org.elasticsearch.common.logging.ESLogger;
8 | import org.elasticsearch.common.logging.Loggers;
9 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestChannel;
10 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestRequest;
11 | import org.elasticsearch.plugins.security.service.SecurityService;
12 | import org.elasticsearch.plugins.security.util.SecurityUtil;
13 | import org.elasticsearch.rest.RestChannel;
14 | import org.elasticsearch.rest.RestFilter;
15 | import org.elasticsearch.rest.RestFilterChain;
16 | import org.elasticsearch.rest.RestRequest;
17 | import org.elasticsearch.rest.RestStatus;
18 |
19 | public abstract class SecureRestFilter extends RestFilter {
20 |
21 | protected final ESLogger log = Loggers.getLogger(this.getClass());
22 |
23 | protected SecurityService securityService;
24 |
25 | protected SecureRestFilter(final SecurityService securityService) {
26 | super();
27 | this.securityService = securityService;
28 | }
29 |
30 | protected InetAddress getClientHostAddress(final RestRequest request)
31 | throws UnknownHostException {
32 |
33 | final InetAddress hostAddress = securityService
34 | .getHostAddressFromRequest(request);
35 |
36 | return hostAddress;
37 | }
38 |
39 | @Override
40 | public final void process(final RestRequest request,
41 | final RestChannel channel, final RestFilterChain filterChain) {
42 |
43 | // TODO check aliases, multiple indices, _all, ...
44 | final List indices = SecurityUtil.getIndices(request);
45 | if (indices.contains(securityService
46 | .getSecurityConfigurationIndex())) {
47 |
48 | try {
49 | if (getClientHostAddress(request).isLoopbackAddress()) {
50 | filterChain.continueProcessing(request, channel);
51 | } else {
52 | SecurityUtil.send(request, channel, RestStatus.FORBIDDEN,
53 | "Only allowed from localhost (loopback)");
54 | }
55 | } catch (final UnknownHostException e) {
56 | SecurityUtil.send(request, channel,
57 | RestStatus.INTERNAL_SERVER_ERROR, e.toString());
58 | }
59 | } else {
60 |
61 | ((TomcatHttpServerRestRequest) request).getUserRoles();
62 |
63 | processSecure((TomcatHttpServerRestRequest) request,
64 | (TomcatHttpServerRestChannel) channel, filterChain);
65 |
66 | }
67 |
68 | }
69 |
70 | protected abstract void processSecure(
71 | final TomcatHttpServerRestRequest request,
72 | final TomcatHttpServerRestChannel channel,
73 | final RestFilterChain filterChain);
74 |
75 | protected abstract String getType();
76 |
77 | protected abstract String getId();
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/realm/AllPermsRealm.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.realm;
2 |
3 | import java.io.IOException;
4 | import java.security.Principal;
5 | import java.util.Arrays;
6 |
7 | import org.apache.catalina.Context;
8 | import org.apache.catalina.Wrapper;
9 | import org.apache.catalina.connector.Request;
10 | import org.apache.catalina.connector.Response;
11 | import org.apache.catalina.deploy.SecurityConstraint;
12 | import org.apache.catalina.realm.GenericPrincipal;
13 | import org.apache.catalina.realm.RealmBase;
14 | import org.ietf.jgss.GSSCredential;
15 |
16 | public class AllPermsRealm extends RealmBase {
17 |
18 | @Override
19 | protected String getName() {
20 | return "AllPermsRealm";
21 | }
22 |
23 |
24 | @Override
25 | protected Principal getPrincipal(String username,
26 | GSSCredential gssCredential) {
27 |
28 | throw new RuntimeException(username+"//"+gssCredential);
29 | }
30 |
31 | @Override
32 | protected String getPassword(String username) {
33 | return null;
34 | }
35 |
36 | @Override
37 | protected Principal getPrincipal(String username) {
38 | return new GenericPrincipal(username, null, Arrays.asList( "*".split("")));
39 | }
40 |
41 | @Override
42 | public boolean hasResourcePermission(Request request, Response response,
43 | SecurityConstraint[] constraints, Context context)
44 | throws IOException {
45 |
46 | return request.getPrincipal() != null;
47 | }
48 |
49 | @Override
50 | public boolean hasRole(Wrapper wrapper, Principal principal, String role) {
51 |
52 | return principal != null;
53 | }
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/realm/LdapTlsContextFactory.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.realm;
2 |
3 | import java.io.IOException;
4 | import java.lang.reflect.InvocationHandler;
5 | import java.lang.reflect.InvocationTargetException;
6 | import java.lang.reflect.Method;
7 | import java.lang.reflect.Proxy;
8 | import java.util.Arrays;
9 | import java.util.HashMap;
10 | import java.util.Hashtable;
11 | import java.util.Map;
12 | import java.util.logging.Logger;
13 |
14 | import javax.naming.Context;
15 | import javax.naming.NamingException;
16 | import javax.naming.directory.DirContext;
17 | import javax.naming.ldap.InitialLdapContext;
18 | import javax.naming.ldap.LdapContext;
19 | import javax.naming.ldap.StartTlsRequest;
20 | import javax.naming.ldap.StartTlsResponse;
21 | import javax.naming.spi.InitialContextFactory;
22 | import javax.net.ssl.HostnameVerifier;
23 | import javax.net.ssl.SSLSession;
24 |
25 | import com.sun.jndi.ldap.LdapCtxFactory;
26 |
27 | public class LdapTlsContextFactory implements InitialContextFactory {
28 |
29 | private static final class ProxyLdapContext implements InvocationHandler {
30 | private final LdapContext delegate;
31 | private final StartTlsResponse tls;
32 |
33 |
34 | private ProxyLdapContext(Hashtable env) throws NamingException {
35 | final Map savedEnv = new HashMap();
36 | for (final String key : Arrays.asList(Context.SECURITY_AUTHENTICATION,
37 | Context.SECURITY_CREDENTIALS, Context.SECURITY_PRINCIPAL,
38 | Context.SECURITY_PROTOCOL)) {
39 | final Object entry = env.remove(key);
40 | if (entry != null) {
41 | savedEnv.put(key, entry);
42 | }
43 | }
44 | delegate = new InitialLdapContext(env, null);
45 | tls = (StartTlsResponse) delegate
46 | .extendedOperation(new StartTlsRequest());
47 | tls.setHostnameVerifier(new HostnameVerifier() {
48 |
49 | @Override
50 | public boolean verify(String hostname, SSLSession session) {
51 | return true;
52 | }
53 | });
54 | try {
55 | final SSLSession negotiate = tls.negotiate();
56 | Logger.getLogger(this.getClass().getCanonicalName()).fine(
57 | "LDAP is now using " + negotiate.getProtocol());
58 | } catch (final IOException e) {
59 | throw new NamingException(e.getMessage());
60 | }
61 | for (final Map.Entry savedEntry : savedEnv.entrySet()) {
62 | delegate.addToEnvironment(savedEntry.getKey(), savedEntry
63 | .getValue());
64 | }
65 | }
66 |
67 | @Override
68 | public Object invoke(Object proxy, Method method, Object[] args)
69 | throws Throwable {
70 | if ("close".equals(method.getName())) {
71 | return doClose(delegate);
72 | }
73 | return method.invoke(delegate, args);
74 | }
75 |
76 | private Object doClose(LdapContext delegate) throws IOException,
77 | IllegalAccessException, InvocationTargetException {
78 | try {
79 | if (tls != null) {
80 | try {
81 | tls.close();
82 | } catch (final IOException e) {
83 | throw new InvocationTargetException(e);
84 | }
85 | }
86 | } finally {
87 | try {
88 | if (delegate != null) {
89 | delegate.close();
90 | }
91 | } catch (final NamingException e) {
92 | throw new InvocationTargetException(e);
93 | }
94 | }
95 | return null;
96 | }
97 | }
98 |
99 | public static final String REAL_INITIAL_CONTEXT_FACTORY = "REAL_INITIAL_CONTEXT_FACTORY";
100 |
101 | @SuppressWarnings("unchecked")
102 | @Override
103 | public Context getInitialContext(final Hashtable environment)
104 | throws NamingException {
105 | final Hashtable proxyEnv = new Hashtable(environment);
106 | Object realFactory;
107 | if (environment.contains(REAL_INITIAL_CONTEXT_FACTORY)) {
108 | realFactory = environment.get(REAL_INITIAL_CONTEXT_FACTORY);
109 | } else {
110 | realFactory = LdapCtxFactory.class.getCanonicalName();
111 | }
112 | proxyEnv.put(Context.INITIAL_CONTEXT_FACTORY, realFactory);
113 | proxyEnv.put("com.sun.jndi.ldap.connect.pool", "false");
114 | return (Context) Proxy.newProxyInstance(this.getClass()
115 | .getClassLoader(), new Class>[] { DirContext.class },
116 | new ProxyLdapContext(proxyEnv));
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/ExtendedJndiRealm.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import java.io.IOException;
4 | import java.security.Principal;
5 | import java.security.cert.X509Certificate;
6 |
7 | import org.apache.catalina.connector.Request;
8 | import org.apache.catalina.connector.Response;
9 | import org.apache.catalina.deploy.SecurityConstraint;
10 | import org.apache.catalina.realm.JNDIRealm;
11 | import org.apache.commons.lang.StringUtils;
12 | import org.apache.juli.logging.Log;
13 | import org.apache.juli.logging.LogFactory;
14 |
15 | public class ExtendedJndiRealm extends JNDIRealm {
16 |
17 | private static final Log log = LogFactory.getLog(ExtendedJndiRealm.class);
18 | private final String sslUserAttribute;
19 | public ExtendedJndiRealm(String sslUserAttribute) {
20 | this.sslUserAttribute=sslUserAttribute;
21 | }
22 |
23 | @Override
24 | public boolean hasResourcePermission(Request request, Response response,
25 | SecurityConstraint[] constraints,
26 | org.apache.catalina.Context context) throws IOException {
27 | // TODO Auto-generated method stub
28 | return request.getPrincipal() != null;
29 | }
30 |
31 | /**
32 | * Return the Principal associated with the given certificate.
33 | */
34 | @Override
35 | protected Principal getPrincipal(X509Certificate usercert) {
36 | final String username = x509UsernameRetriever.getUsername(usercert);
37 |
38 | if(log.isDebugEnabled()) {
39 | log.debug(sm.getString("realmBase.gotX509Username", username));
40 | }
41 |
42 |
43 | if(sslUserAttribute != null && !sslUserAttribute.isEmpty()) {
44 | return getPrincipal(StringUtils.substringBetween(username, sslUserAttribute+"=",",")); //TODO fix case
45 | } else {
46 | return super.getPrincipal(username);
47 | }
48 | }
49 |
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/ExtendedSpnegoAuthenticator.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import org.apache.catalina.authenticator.SpnegoAuthenticator;
4 |
5 |
6 |
7 | public class ExtendedSpnegoAuthenticator extends SpnegoAuthenticator {
8 |
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/ExtendedTomcat.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import org.apache.catalina.startup.Tomcat;
4 | import org.elasticsearch.common.logging.ESLogger;
5 | import org.elasticsearch.common.logging.Loggers;
6 |
7 | public class ExtendedTomcat extends Tomcat {
8 |
9 | protected static final ESLogger log = Loggers
10 | .getLogger(ExtendedTomcat.class);
11 |
12 | public ExtendedTomcat() {
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/TomcatHttpServerRestChannel.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.concurrent.CountDownLatch;
8 |
9 | import javax.servlet.ServletOutputStream;
10 | import javax.servlet.http.HttpServletResponse;
11 |
12 | import org.elasticsearch.common.bytes.BytesReference;
13 | import org.elasticsearch.common.collect.Tuple;
14 | import org.elasticsearch.common.logging.ESLogger;
15 | import org.elasticsearch.common.logging.Loggers;
16 | import org.elasticsearch.common.xcontent.XContent;
17 | import org.elasticsearch.common.xcontent.XContentBuilder;
18 | import org.elasticsearch.common.xcontent.XContentFactory;
19 | import org.elasticsearch.common.xcontent.XContentHelper;
20 | import org.elasticsearch.common.xcontent.XContentType;
21 | import org.elasticsearch.common.xcontent.support.XContentMapValues;
22 | import org.elasticsearch.http.HttpChannel;
23 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
24 | import org.elasticsearch.plugins.security.filter.PermDlsEvaluator;
25 | import org.elasticsearch.plugins.security.service.SecurityService;
26 | import org.elasticsearch.plugins.security.service.permission.DlsPermission;
27 | import org.elasticsearch.plugins.security.util.SecurityUtil;
28 | import org.elasticsearch.rest.BytesRestResponse;
29 | import org.elasticsearch.rest.RestRequest;
30 | import org.elasticsearch.rest.RestResponse;
31 |
32 | public class TomcatHttpServerRestChannel extends HttpChannel {
33 |
34 | protected final ESLogger log = Loggers.getLogger(this.getClass());
35 |
36 | private final TomcatHttpServerRestRequest restRequest;
37 |
38 | private final HttpServletResponse resp;
39 |
40 | private Exception sendFailure;
41 |
42 | private final CountDownLatch latch;
43 |
44 | private final SecurityService securityService;
45 |
46 | final Boolean enableDls;
47 |
48 | public TomcatHttpServerRestChannel(
49 | final TomcatHttpServerRestRequest restRequest,
50 | final HttpServletResponse resp,
51 | final SecurityService securityService) {
52 | super(restRequest);
53 | this.securityService = securityService;
54 | this.restRequest = restRequest;
55 | this.resp = resp;
56 | latch = new CountDownLatch(1);
57 |
58 | enableDls = securityService.getSettings().getAsBoolean(
59 | "security.module.dls.enabled", true);
60 |
61 | }
62 |
63 | public void await() throws InterruptedException {
64 | latch.await();
65 | }
66 |
67 | public Exception sendFailure() {
68 | return sendFailure;
69 | }
70 |
71 | @Override
72 | public void sendResponse(final RestResponse response) {
73 |
74 | resp.setContentType(response.contentType());
75 |
76 | //CORS
77 | resp.addHeader("Access-Control-Allow-Origin", "*");
78 | //enhancing the list of allowed method list to meet the requirements of Kibana (contributed by Ram Kotamaraja)
79 | resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
80 | resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length, X-HTTP-Method-Override, Origin, Accept, Authorization");
81 | //resp.addHeader("Access-Control-Allow-Credentials", "true");
82 | resp.addHeader("Cache-Control", "max-age=0");
83 |
84 |
85 | if (response.status() != null) {
86 | resp.setStatus(response.status().getStatus());
87 | } else {
88 | resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
89 | }
90 | /*if (restRequest.method() == RestRequest.Method.OPTIONS) {
91 | // TODO: also add more access control parameters
92 | resp.addHeader("Access-Control-Max-Age", "1728000");
93 |
94 |
95 |
96 | }*/
97 | try {
98 |
99 | log.debug("Rest response contentype: "+response.contentType()+"/xcontent response contentype: "+ XContentType.fromRestContentType(response.contentType()));
100 |
101 | if(enableDls && SecurityUtil.xContentTypefromRestContentType(response.contentType()) != null) { //skip text/html etc) {
102 | log.debug("DLS is enabled and request contains valid xcontent");
103 | BytesReference modifiedContent = applyDls((BytesRestResponse)response);
104 | int contentLength = modifiedContent.length();
105 | resp.setContentLength(contentLength);
106 | final ServletOutputStream out = resp.getOutputStream();
107 | modifiedContent.writeTo(out);
108 | out.close();
109 |
110 | } else {
111 | log.debug("DLS is not enabled or response does not contain valid xcontent");
112 | int contentLength = response.content().length();
113 | resp.setContentLength(contentLength);
114 | ServletOutputStream out = resp.getOutputStream();
115 | response.content().writeTo(out);
116 | out.close();
117 | }
118 |
119 |
120 |
121 |
122 | } catch (final Exception e) {
123 | log.error(e.toString(), e);
124 | sendFailure = e;
125 | } finally {
126 | latch.countDown();
127 | }
128 | }
129 |
130 | protected BytesReference applyDls(final BytesRestResponse xres)
131 | throws IOException, MalformedConfigurationException {
132 |
133 |
134 | final List indices = SecurityUtil.getIndices(restRequest);
135 |
136 | log.debug("applyDLS() for indices "+indices);
137 |
138 | if (indices.contains(securityService
139 | .getSecurityConfigurationIndex())) {
140 |
141 | if (securityService
142 | .getHostAddressFromRequest(restRequest)
143 | .isLoopbackAddress()) {
144 |
145 | log.debug("applyDLS() return unmodified content because of loopback address");
146 | return xres.content();
147 |
148 | } else {
149 | throw new IOException("Only allowed from localhost (loopback)");
150 | }
151 |
152 | }
153 |
154 | if(xres.content() == null || xres.content().length() == 0) {
155 | log.debug("applyDLS() return unmodified content because of content is null or of zero length");
156 | return xres.content();
157 | }
158 |
159 | if (xres.status().getStatus() < 200
160 | || xres.status().getStatus() >= 300) {
161 |
162 | log.debug("applyDLS() return unmodified content because of status "+xres.status().getStatus());
163 | return xres.content();
164 | }
165 |
166 | if ( !restRequest.path().contains("_search")
167 | && !restRequest.path().contains("_msearch")
168 | && !restRequest.path().contains("_mlt")
169 | && !restRequest.path().contains("_suggest")
170 | && !restRequest.getHttpServletRequest().getMethod().equalsIgnoreCase("get") ) {
171 |
172 | log.debug("applyDLS() return unmodified content because of path (no search): "+restRequest.getHttpServletRequest().getMethod()+" "+restRequest.path());
173 | return xres.content();
174 | }
175 |
176 | final List dlsTokens = new PermDlsEvaluator(
177 | securityService.getXContentSecurityConfiguration(
178 | "dlspermissions", "dlspermissions")).evaluatePerm(
179 | SecurityUtil.getIndices(restRequest),
180 | SecurityUtil.getTypes(restRequest),
181 | securityService
182 | .getHostAddressFromRequest(restRequest),
183 | new TomcatUserRoleCallback(restRequest
184 | .getHttpServletRequest(),securityService.getSettings().get("security.ssl.userattribute")));
185 |
186 | log.debug("dls tokens: " + dlsTokens);
187 |
188 | // this.log.debug("orig json: " + xres.builder().string());
189 |
190 | final List perms = securityService
191 | .parseDlsPermissions(xres.content());
192 |
193 | // TODO check against the tokens
194 |
195 | final Tuple> mapTuple = XContentHelper
196 | .convertToMap(xres.content().toBytes(), true);
197 |
198 | final List fields = new ArrayList();
199 | fields.add("_shards*");
200 | fields.add("took");
201 | fields.add("timed_out");
202 | fields.add("hits.total");
203 | fields.add("hits.max_score");
204 | fields.add("hits.hits._index");
205 | fields.add("hits.hits._type");
206 | fields.add("hits.hits._id");
207 | fields.add("hits.hits._score");
208 |
209 | //GET
210 | fields.add("_index");
211 | fields.add("_type");
212 | fields.add("_version");
213 | fields.add("_id");
214 | fields.add("found");
215 |
216 |
217 | if(!securityService.isStrictModeEnabled()){
218 | fields.add("facets");
219 | fields.add("suggest");
220 | }
221 |
222 |
223 | for (final DlsPermission p : perms) {
224 |
225 | log.debug(p.toString());
226 |
227 | if (p.isAnyTokenAllowedToRead(dlsTokens)) {
228 |
229 | fields.add("hits.hits._source." + p.getField());
230 | fields.add("_source." + p.getField());
231 | }
232 |
233 | }
234 |
235 | log.debug(fields.toString());
236 |
237 | final Map filteredSource = XContentMapValues.filter(
238 | mapTuple.v2(), fields.toArray(new String[0]), null);
239 |
240 | log.debug("filteredSource " + filteredSource);
241 |
242 | final XContentBuilder sourceToBeReturned = XContentFactory
243 | .contentBuilder(mapTuple.v1()).map(filteredSource);
244 | return sourceToBeReturned.bytes();
245 |
246 | }
247 |
248 | }
249 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/TomcatHttpServerRestRequest.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import java.io.IOException;
4 | import java.security.Principal;
5 | import java.util.Arrays;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.Map.Entry;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 |
13 | import org.apache.catalina.realm.GenericPrincipal;
14 | import org.elasticsearch.common.bytes.BytesArray;
15 | import org.elasticsearch.common.bytes.BytesReference;
16 | import org.elasticsearch.common.io.Streams;
17 | import org.elasticsearch.common.logging.ESLogger;
18 | import org.elasticsearch.common.logging.Loggers;
19 | import org.elasticsearch.http.HttpRequest;
20 |
21 | import org.elasticsearch.rest.support.RestUtils;
22 |
23 | import waffle.servlet.WindowsPrincipal;
24 |
25 | public class TomcatHttpServerRestRequest extends
26 | HttpRequest {
27 |
28 | protected static final ESLogger log = Loggers
29 | .getLogger(TomcatHttpServerRestRequest.class);
30 |
31 | public static final String REQUEST_CONTENT_ATTRIBUTE = "org.elasticsearch.plugins.security.http.tomcat.request-content";
32 |
33 | private final HttpServletRequest request;
34 |
35 | private final Method method;
36 |
37 | private final Map params;
38 |
39 | private BytesReference content;
40 |
41 | private final String opaqueId;
42 |
43 | public TomcatHttpServerRestRequest(final HttpServletRequest request)
44 | throws IOException {
45 | this.request = request;
46 | opaqueId = request.getHeader("X-Opaque-Id");
47 | method = Method.valueOf(request.getMethod());
48 | params = new HashMap();
49 |
50 | log.debug("HttpServletRequest impl class: " + request.getClass());
51 | log.debug("HttpServletRequest ru: " + request.getRemoteUser());
52 | log.debug("HttpServletRequest up: " + request.getUserPrincipal());
53 | //log.debug("HttpServletRequest up: " + request.getUserPrincipal().getClass().toString());
54 |
55 | if (request.getQueryString() != null) {
56 | RestUtils.decodeQueryString(request.getQueryString(), 0,
57 | params);
58 | }
59 |
60 | content = new BytesArray(Streams.copyToByteArray(request
61 | .getInputStream()));
62 | request.setAttribute(REQUEST_CONTENT_ATTRIBUTE, content);
63 | }
64 |
65 | @Override
66 | public Method method() {
67 | return method;
68 | }
69 |
70 | @Override
71 | public String uri() {
72 |
73 | return request.getRequestURI();
74 |
75 | /*
76 | * int prefixLength = 0; if (request.getContextPath() != null ) {
77 | * prefixLength += request.getContextPath().length(); } if
78 | * (request.getServletPath() != null ) { prefixLength +=
79 | * request.getServletPath().length(); } if (prefixLength > 0) { return
80 | * request.getRequestURI().substring(prefixLength); } else { return
81 | * request.getRequestURI(); }
82 | */
83 | }
84 |
85 | @Override
86 | public String rawPath() {
87 | return uri();
88 | }
89 |
90 | @Override
91 | public boolean hasContent() {
92 | return content.length() > 0;
93 | }
94 |
95 | @Override
96 | public boolean contentUnsafe() {
97 | return false;
98 | }
99 |
100 | @Override
101 | public BytesReference content() {
102 | return content;
103 | }
104 |
105 | @Override
106 | public String header(final String name) {
107 | return request.getHeader(name);
108 | }
109 |
110 | @Override
111 | public Map params() {
112 | return params;
113 | }
114 |
115 | @Override
116 | public boolean hasParam(final String key) {
117 | return params.containsKey(key);
118 | }
119 |
120 | @Override
121 | public String param(final String key) {
122 | return params.get(key);
123 | }
124 |
125 | @Override
126 | public String param(final String key, final String defaultValue) {
127 | final String value = params.get(key);
128 | if (value == null) {
129 | return defaultValue;
130 | }
131 | return value;
132 | }
133 |
134 | public String localAddr() {
135 | return request.getLocalAddr();
136 | }
137 |
138 | public long localPort() {
139 | return request.getLocalPort();
140 | }
141 |
142 | public String remoteAddr() {
143 | return request.getRemoteAddr();
144 | }
145 |
146 | public long remotePort() {
147 | return request.getRemotePort();
148 | }
149 |
150 | public String remoteUser() {
151 | return request.getRemoteUser();
152 | }
153 |
154 | public String scheme() {
155 | return request.getScheme();
156 | }
157 |
158 | public String contentType() {
159 | return request.getContentType();
160 | }
161 |
162 | public String opaqueId() {
163 | return opaqueId;
164 | }
165 |
166 | public HttpServletRequest getHttpServletRequest() {
167 | return request;
168 |
169 | }
170 |
171 | public Principal getUserPrincipal() {
172 | return request.getUserPrincipal();
173 |
174 | }
175 |
176 | public boolean isUserInRole(final String role) {
177 | return request.isUserInRole(role);
178 |
179 | }
180 |
181 | public List getUserRoles() {
182 |
183 | if (request.getUserPrincipal() instanceof GenericPrincipal) {
184 | final GenericPrincipal wp = (GenericPrincipal) request
185 | .getUserPrincipal();
186 |
187 | if (wp.getRoles() != null) {
188 | final List roles = Arrays.asList(wp.getRoles());
189 | log.debug("GenericPrincipal roles: " + roles);
190 | return roles;
191 | }
192 | }
193 |
194 |
195 | if (request.getUserPrincipal() instanceof WindowsPrincipal) {
196 | final WindowsPrincipal wp = (WindowsPrincipal) request
197 | .getUserPrincipal();
198 |
199 | log.debug("WindowsPrincipal roles: " + wp.getRolesString());
200 | log.debug("WindowsPrincipal groups: " + wp.getGroups());
201 |
202 | if (wp.getRolesString() != null) {
203 | return Arrays.asList(wp.getRolesString().split(","));
204 | }
205 | }
206 |
207 | /*if (this.request.getUserPrincipal() instanceof ActiveDirectoryPrincipal) {
208 | final ActiveDirectoryPrincipal ap = (ActiveDirectoryPrincipal) this.request
209 | .getUserPrincipal();
210 |
211 | log.debug("ActiveDirectoryPrincipal roles: " + ap.getRoles());
212 |
213 | return ap.getRoles();
214 | }*/
215 |
216 | return null;
217 |
218 | }
219 |
220 | @Override
221 | public Iterable> headers() {
222 |
223 | Map headerMap = new HashMap();
224 |
225 | while(request.getHeaderNames().hasMoreElements())
226 | {
227 | String headerName = request.getHeaderNames().nextElement();
228 | headerMap.put(headerName, request.getHeader(headerName));
229 | }
230 |
231 | return headerMap.entrySet();
232 | }
233 |
234 |
235 | //next three methods contributed by Ram Kotamaraja
236 |
237 | /**
238 | * Setter Method for content
239 | */
240 | public void setContent(BytesReference content) {
241 | this.content = content;
242 | }
243 |
244 | /**
245 | * Getter Method for returning content
246 | * @return BytesReference
247 | */
248 | public BytesReference getContent() {
249 | return content;
250 | }
251 |
252 | /**
253 | * Method added to modify the request query based on the authorization permission settings
254 | * in the security configuration. This method will set the modified content in request.
255 | * @param requestContentAttribute
256 | * @param content
257 | */
258 | public void setAttribute(String requestContentAttribute,
259 | BytesReference content) {
260 | this.request.setAttribute(requestContentAttribute, content);
261 |
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/TomcatHttpServerTransportModule.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import org.elasticsearch.common.inject.AbstractModule;
4 | import org.elasticsearch.http.HttpServerTransport;
5 |
6 | public class TomcatHttpServerTransportModule extends AbstractModule {
7 | @Override
8 | protected void configure() {
9 | this.bind(HttpServerTransport.class)
10 | .to(TomcatHttpServerTransport.class).asEagerSingleton();
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/TomcatHttpTransportHandlerServlet.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.ServletException;
6 | import javax.servlet.http.HttpServlet;
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 |
10 | import org.elasticsearch.common.logging.ESLogger;
11 | import org.elasticsearch.common.logging.Loggers;
12 | import org.elasticsearch.http.HttpServerAdapter;
13 |
14 | public class TomcatHttpTransportHandlerServlet extends HttpServlet {
15 |
16 | /**
17 | *
18 | */
19 | private static final long serialVersionUID = 1L;
20 | protected static final ESLogger log = Loggers
21 | .getLogger(TomcatHttpTransportHandlerServlet.class);
22 | private volatile TomcatHttpServerTransport transport;
23 |
24 | public TomcatHttpTransportHandlerServlet() {
25 |
26 | }
27 |
28 | @Override
29 | protected void service(final HttpServletRequest req,
30 | final HttpServletResponse resp) throws ServletException,
31 | IOException {
32 |
33 | final HttpServerAdapter adapter = getTransport()
34 | .httpServerAdapter();
35 | final TomcatHttpServerRestRequest restRequest = new TomcatHttpServerRestRequest(
36 | req);
37 | final TomcatHttpServerRestChannel restChannel = new TomcatHttpServerRestChannel(
38 | restRequest, resp, transport.getSecurityService());
39 |
40 | try {
41 |
42 | adapter.dispatchRequest(restRequest, restChannel);
43 | restChannel.await();
44 |
45 | } catch (final InterruptedException e) {
46 | throw new ServletException("failed to dispatch request", e);
47 | } catch (final Exception e) {
48 | throw new IOException("failed to dispatch request", e);
49 | }
50 | if (restChannel.sendFailure() != null) {
51 | throw new ServletException(restChannel.sendFailure());
52 | }
53 |
54 | }
55 |
56 | public TomcatHttpServerTransport getTransport() {
57 | return transport;
58 | }
59 |
60 | public void setTransport(final TomcatHttpServerTransport transport) {
61 | this.transport = transport;
62 | // this.logger = Loggers.getLogger(buildClassLoggerName(getClass()),
63 | // transport.settings());
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/http/tomcat/TomcatUserRoleCallback.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.http.tomcat;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | import org.apache.commons.lang.StringUtils;
6 | import org.elasticsearch.plugins.security.service.permission.UserRoleCallback;
7 |
8 | public class TomcatUserRoleCallback implements UserRoleCallback {
9 |
10 | private final HttpServletRequest request;
11 | private final String sslUserAttribute;
12 |
13 | public TomcatUserRoleCallback(final HttpServletRequest request, String sslUserAttribute) {
14 | this.request = request;
15 | this.sslUserAttribute=sslUserAttribute;
16 | }
17 |
18 | @Override
19 | public String getRemoteuser() {
20 |
21 |
22 | String remoteUser = request.getRemoteUser();
23 |
24 | //CN=nelsonh, OU=marketingc, O=Saly Test Inc 2, DC=saly, DC=de
25 | if(remoteUser != null && !remoteUser.isEmpty())
26 | {
27 | if(sslUserAttribute != null && remoteUser.contains(sslUserAttribute))
28 | {
29 | remoteUser = StringUtils.substringBetween(remoteUser.toLowerCase(), //TODO fix lower case
30 | (sslUserAttribute+"=").toLowerCase(), ",");
31 | }
32 | }
33 |
34 | return remoteUser;
35 | }
36 |
37 | @Override
38 | public boolean isRemoteUserInRole(final String role) {
39 |
40 | return request.isUserInRole(role);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/service/SecurityService.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.service;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.net.UnknownHostException;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.Collection;
9 | import java.util.HashMap;
10 | import java.util.HashSet;
11 | import java.util.List;
12 | import java.util.Map;
13 | import java.util.Set;
14 |
15 | import net.minidev.json.JSONArray;
16 | import net.minidev.json.JSONObject;
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | import org.elasticsearch.ElasticsearchException;
25 | import org.elasticsearch.action.get.GetResponse;
26 | import org.elasticsearch.client.Client;
27 | import org.elasticsearch.common.bytes.BytesReference;
28 | import org.elasticsearch.common.component.AbstractLifecycleComponent;
29 | import org.elasticsearch.common.inject.Inject;
30 | import org.elasticsearch.common.settings.Settings;
31 | import org.elasticsearch.common.xcontent.XContentHelper;
32 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
33 | import org.elasticsearch.plugins.security.filter.ActionPathFilter;
34 | import org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerRestRequest;
35 | import org.elasticsearch.plugins.security.service.permission.DlsPermission;
36 | import org.elasticsearch.rest.RestController;
37 | import org.elasticsearch.rest.RestRequest;
38 |
39 | import com.jayway.jsonpath.JsonPath;
40 |
41 | public class SecurityService extends
42 | AbstractLifecycleComponent {
43 |
44 | public Settings getSettings() {
45 | return settings;
46 | }
47 |
48 | private final static String DEFAULT_SECURITY_CONFIG_INDEX = "securityconfiguration";
49 | private final String securityConfigurationIndex;
50 | private final RestController restController;
51 | private final Client client;
52 | private final Settings settings;
53 | private final boolean strictModeEnabled;
54 |
55 | @Inject
56 | public SecurityService(final Settings settings, final Client client,
57 | final RestController restController) {
58 | super(settings);
59 |
60 | this.settings = settings;
61 | this.restController = restController;
62 | this.client = client;
63 | securityConfigurationIndex = settings.get(
64 | "security.configuration.index", DEFAULT_SECURITY_CONFIG_INDEX);
65 |
66 | strictModeEnabled = settings.getAsBoolean(
67 | "security.strict", false);
68 |
69 | }
70 |
71 | public boolean isStrictModeEnabled() {
72 | return strictModeEnabled;
73 | }
74 |
75 | public Client getClient() {
76 | return client;
77 | }
78 |
79 | @Override
80 | protected void doStart() throws ElasticsearchException {
81 |
82 | // TODO order
83 |
84 | final Boolean enableActionPathFilter = settings.getAsBoolean(
85 | "security.module.actionpathfilter.enabled", true);
86 |
87 | if (enableActionPathFilter != null
88 | && enableActionPathFilter.booleanValue()) {
89 | restController.registerFilter(new ActionPathFilter(this));
90 | }
91 |
92 | // this.restController
93 | // .registerFilter(new FieldLevelPermissionFilter(this));
94 | // this.restController.registerFilter(new FieldResponseFilter(this));
95 |
96 | // this.logger.debug("security.configuration.index="
97 | // + this.securityConfigurationIndex);
98 |
99 | // TODO disable dynamic scripting for this node
100 | // https://github.com/yakaz/elasticsearch-action-reloadsettings/blob/master/src/main/java/org/elasticsearch/action/reloadsettings/ESInternalSettingsPerparer.java
101 | // client.execute(action, request)
102 |
103 | }
104 |
105 | @Override
106 | protected void doStop() throws ElasticsearchException {
107 |
108 | logger.debug("doStop");
109 | }
110 |
111 | @Override
112 | protected void doClose() throws ElasticsearchException {
113 | logger.debug("doClose");
114 |
115 | }
116 |
117 | public String getXContentSecurityConfiguration(final String type,
118 | final String id) throws IOException,
119 | MalformedConfigurationException {
120 | try {
121 | return XContentHelper.convertToJson(
122 | getXContentSecurityConfigurationAsBR(type, id), true);
123 | } catch (final IOException e) {
124 | logger.error("Unable to load type {} and id {} due to {}",
125 | type, id, e);
126 | return null;
127 | }
128 | }
129 |
130 | public BytesReference getXContentSecurityConfigurationAsBR(
131 | final String type, final String id)
132 | throws MalformedConfigurationException {
133 | final GetResponse resp = client
134 | .prepareGet(securityConfigurationIndex, type, id)
135 | .setRefresh(true).setOperationThreaded(false).get();
136 |
137 | if (resp.isExists()) {
138 | return resp.getSourceAsBytesRef();
139 | } else {
140 | throw new MalformedConfigurationException("document type " + type
141 | + " with id " + id + " does not exists");
142 | }
143 | }
144 |
145 | public String getSecurityConfigurationIndex() {
146 | return securityConfigurationIndex;
147 | }
148 |
149 | public InetAddress getHostAddressFromRequest(final RestRequest request)
150 | throws UnknownHostException {
151 |
152 | // this.logger.debug(request.getClass().toString());
153 |
154 | final String oaddr = ((TomcatHttpServerRestRequest) request).remoteAddr();
155 | // this.logger.debug("original hostname: " + addr);
156 |
157 | String raddr = oaddr;
158 |
159 | if (oaddr == null || oaddr.isEmpty()) {
160 | throw new UnknownHostException("Original host is or ");
161 | }
162 |
163 | final InetAddress iaddr = InetAddress.getByName(oaddr);
164 |
165 | // security.http.xforwardfor.header
166 | // security.http.xforwardfor.trustedproxies
167 | // security.http.xforwardfor.enforce
168 | final String xForwardedForHeader = settings
169 | .get("security.http.xforwardedfor.header");
170 |
171 | if (xForwardedForHeader != null && !xForwardedForHeader.isEmpty()) {
172 |
173 | final String xForwardedForValue = request
174 | .header(xForwardedForHeader);
175 |
176 | logger.debug("xForwardedForHeader is " + xForwardedForHeader
177 | + ":" + xForwardedForValue);
178 |
179 | final String xForwardedTrustedProxiesS = settings
180 | .get("security.http.xforwardedfor.trustedproxies");
181 | // TODO use yaml list
182 | final String[] xForwardedTrustedProxies = xForwardedTrustedProxiesS == null ? new String[0]
183 | : xForwardedTrustedProxiesS.replace(" ", "").split(",");
184 |
185 | final boolean xForwardedEnforce = settings.getAsBoolean(
186 | "security.http.xforwardedfor.enforce", false);
187 |
188 | if (xForwardedForValue != null && !xForwardedForValue.isEmpty()) {
189 | final List addresses = Arrays.asList(xForwardedForValue
190 | .replace(" ", "").split(","));
191 | final List proxiesPassed = new ArrayList(
192 | addresses.subList(1, addresses.size()));
193 |
194 | if (xForwardedTrustedProxies.length == 0) {
195 | throw new UnknownHostException("No trusted proxies");
196 | }
197 |
198 | proxiesPassed
199 | .removeAll(Arrays.asList(xForwardedTrustedProxies));
200 |
201 | logger.debug(proxiesPassed.size() + "/" + proxiesPassed);
202 |
203 | if (proxiesPassed.size() == 0
204 | && (Arrays.asList(xForwardedTrustedProxies).contains(
205 | oaddr) || iaddr.isLoopbackAddress())) {
206 |
207 | raddr = addresses.get(0).trim();
208 |
209 | } else {
210 | throw new UnknownHostException(
211 | "Not all proxies are trusted");
212 | }
213 |
214 | } else {
215 | if (xForwardedEnforce) {
216 | throw new UnknownHostException(
217 | "Forward header enforced but not present");
218 | }
219 | }
220 |
221 | }
222 |
223 | if (raddr == null || raddr.isEmpty()) {
224 | throw new UnknownHostException("Host is or ");
225 | }
226 |
227 | if(raddr.equals(oaddr)) {
228 | return iaddr;
229 | } else {
230 | // if null or "" then loopback is returned
231 | return InetAddress.getByName(raddr);
232 | }
233 |
234 | }
235 |
236 | @SuppressWarnings("unchecked")
237 | public List parseDlsPermissions(final BytesReference br)
238 | throws IOException, MalformedConfigurationException {
239 |
240 | final List perms = new ArrayList();
241 |
242 | final List dlsPermissions = new ArrayList();
243 |
244 | String json = XContentHelper.convertToJson(br, false);
245 |
246 | if (json.contains("\"hits\":{\"total\":0,\"max_score\":null")) {
247 | // no hits
248 | logger.debug("No hits, return ALL permissions");
249 | perms.add(DlsPermission.ALL_PERMISSION);
250 | return perms;
251 | }
252 |
253 | if (!json.contains("dlspermissions")) {
254 | json = XContentHelper.convertToJson(getXContentSecurityConfigurationAsBR("dlspermissions",
255 | "default"), false);
256 | }
257 |
258 | if (json.contains("_source")) {
259 | dlsPermissions.addAll((List) JsonPath.read(json,
260 | "$.hits.hits[*]._source.dlspermissions"));
261 | } else {
262 | dlsPermissions.add((JSONObject) JsonPath.read(json,
263 | "$.dlspermissions"));
264 | }
265 |
266 | for (final JSONObject dlsPermission : dlsPermissions) {
267 |
268 | if (dlsPermission == null) {
269 | continue;
270 | }
271 |
272 | for (final String field : dlsPermission.keySet()) {
273 |
274 | final DlsPermission dlsPerm = new DlsPermission();
275 | dlsPerm.setField(field);
276 |
277 | JSONArray ja = (JSONArray) ((JSONObject) dlsPermission
278 | .get(field)).get("read");
279 | dlsPerm.addReadTokens(ja.toArray(new String[0]));
280 |
281 | ja = (JSONArray) ((JSONObject) dlsPermission.get(field))
282 | .get("update");
283 | dlsPerm.addUpdateTokens(ja.toArray(new String[0]));
284 |
285 | ja = (JSONArray) ((JSONObject) dlsPermission.get(field))
286 | .get("delete");
287 | dlsPerm.addDeleteTokens(ja.toArray(new String[0]));
288 |
289 | perms.add(dlsPerm);
290 | }
291 |
292 | }
293 |
294 | return perms;
295 |
296 | }
297 |
298 | /**
299 | * (contributed by Ram Kotamaraja)
300 | * @param indices - List of ES indices. Now supports only one index at a time.
301 | * @return returns list of types configured in kibana security configuration
302 | * @throws IOException
303 | * @throws MalformedConfigurationException
304 | */
305 | @SuppressWarnings("unchecked")
306 | public List getKibanaTypes(List indices)
307 | throws IOException, MalformedConfigurationException {
308 |
309 | // TODO - Support multiple indices return map
310 | final Map permsMap = new HashMap();
311 |
312 | final Set perms = new HashSet();
313 |
314 | final List kibanaPermissions = new ArrayList();
315 |
316 | String json = null;
317 |
318 | json = XContentHelper.convertToJson(getXContentSecurityConfigurationAsBR("actionpathfilter",
319 | "kibana"), false);
320 |
321 | //logger.debug("Kibana Configuration: "+ json );
322 |
323 | if(JsonPath.parse(json) != null){
324 | kibanaPermissions.addAll((List) JsonPath.read(json,"rules"));
325 | }
326 |
327 | //logger.debug("After $.rules: "+ kibanaPermissions);
328 |
329 | kibanaLoop:
330 | for (final JSONObject kibanaPermission : kibanaPermissions) {
331 |
332 | if (kibanaPermission == null) {
333 | continue;
334 | }
335 |
336 |
337 | String index = null;
338 |
339 | //logger.debug("indices: "+indices);
340 | permLoop:
341 | for (final String field : kibanaPermission.keySet()) {
342 |
343 |
344 | //logger.debug("field: "+field + " :"+kibanaPermission.get(field));
345 | //logger.debug("list contains ? "+indices.contains(kibanaPermission.get(field).toString().trim()));
346 |
347 |
348 | if(index == null && field.equals("index")
349 | && !indices.contains(kibanaPermission.get(field).toString())){
350 | continue kibanaLoop;
351 | }else
352 | if(index == null && field.equals("index")
353 | && indices.contains(kibanaPermission.get(field).toString().trim())){
354 |
355 | index = kibanaPermission.get(field).toString();
356 | continue permLoop;
357 | }else
358 | if(index != null){
359 |
360 | //logger.debug("field: types :"+kibanaPermission.get("types").getClass());
361 | perms.addAll((Collection extends String>) kibanaPermission.get("types"));
362 |
363 | index = null;
364 | }
365 | }
366 | }
367 |
368 | //logger.debug("kibana perm list:"+ perms);
369 |
370 | List returnPerms = new ArrayList();
371 | returnPerms.addAll(perms);
372 |
373 | return returnPerms;
374 |
375 | }
376 |
377 |
378 | }
379 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/service/permission/DlsPermission.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.service.permission;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | public class DlsPermission {
8 |
9 | public static DlsPermission ALL_PERMISSION = new DlsPermission();
10 |
11 | static {
12 | ALL_PERMISSION.addDeleteToken("*");
13 | ALL_PERMISSION.addReadToken("*");
14 | ALL_PERMISSION.addUpdateToken("*");
15 | ALL_PERMISSION.setField("*");
16 | }
17 |
18 | private final List readTokens = new ArrayList();
19 | private final List updateTokens = new ArrayList();
20 | private final List deleteTokens = new ArrayList();
21 | private String field;
22 |
23 | public void setField(final String field) {
24 | this.field = field.trim();
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return "DlsPermission [readTokens=" + readTokens
30 | + ", updateTokens=" + updateTokens + ", deleteTokens="
31 | + deleteTokens + ", field=" + field
32 | + ", isDefault()=" + isDefault() + "]";
33 | }
34 |
35 | @Override
36 | public int hashCode() {
37 | final int prime = 31;
38 | int result = 1;
39 | result = prime
40 | * result
41 | + (deleteTokens == null ? 0 : deleteTokens.hashCode());
42 | result = prime * result
43 | + (field == null ? 0 : field.hashCode());
44 | result = prime * result
45 | + (readTokens == null ? 0 : readTokens.hashCode());
46 | result = prime
47 | * result
48 | + (updateTokens == null ? 0 : updateTokens.hashCode());
49 | return result;
50 | }
51 |
52 | @Override
53 | public boolean equals(final Object obj) {
54 | if (this == obj) {
55 | return true;
56 | }
57 | if (obj == null) {
58 | return false;
59 | }
60 | if (this.getClass() != obj.getClass()) {
61 | return false;
62 | }
63 | final DlsPermission other = (DlsPermission) obj;
64 | if (deleteTokens == null) {
65 | if (other.deleteTokens != null) {
66 | return false;
67 | }
68 | } else if (!deleteTokens.equals(other.deleteTokens)) {
69 | return false;
70 | }
71 | if (field == null) {
72 | if (other.field != null) {
73 | return false;
74 | }
75 | } else if (!field.equals(other.field)) {
76 | return false;
77 | }
78 | if (readTokens == null) {
79 | if (other.readTokens != null) {
80 | return false;
81 | }
82 | } else if (!readTokens.equals(other.readTokens)) {
83 | return false;
84 | }
85 | if (updateTokens == null) {
86 | if (other.updateTokens != null) {
87 | return false;
88 | }
89 | } else if (!updateTokens.equals(other.updateTokens)) {
90 | return false;
91 | }
92 | return true;
93 | }
94 |
95 | public DlsPermission() {
96 |
97 | }
98 |
99 | public boolean isDefault() {
100 | return field.equals("*");
101 | }
102 |
103 | public boolean isAllowNone() {
104 | return readTokens.isEmpty() && updateTokens.isEmpty()
105 | && deleteTokens.isEmpty();
106 | }
107 |
108 | public boolean isTokenAllowedToRead(final String token) {
109 | return readTokens.contains(token) || readTokens.contains("*");
110 | }
111 |
112 | public boolean isTokenAllowedToUpdate(final String token) {
113 | return updateTokens.contains(token)
114 | || updateTokens.contains("*");
115 | }
116 |
117 | public boolean isTokenAllowedToDelete(final String token) {
118 | return deleteTokens.contains(token)
119 | || deleteTokens.contains("*");
120 | }
121 |
122 | public boolean isAnyTokenAllowedToDelete(final List tokens) {
123 | return !Collections.disjoint(deleteTokens, tokens)
124 | || deleteTokens.contains("*");
125 | }
126 |
127 | public boolean isAnyTokenAllowedToRead(final List tokens) {
128 | return !Collections.disjoint(readTokens, tokens)
129 | || readTokens.contains("*");
130 | }
131 |
132 | public boolean isAnyTokenAllowedToUpdate(final List tokens) {
133 | return !Collections.disjoint(updateTokens, tokens)
134 | || updateTokens.contains("*");
135 | }
136 |
137 | public String getField() {
138 | return field;
139 | }
140 |
141 | public void addReadToken(final String token) {
142 | addToken(token, readTokens);
143 | }
144 |
145 | public void addReadTokens(final String[] tokens) {
146 | for (final String token : tokens) {
147 | addToken(token, readTokens);
148 | }
149 | }
150 |
151 | public void addUpdateTokens(final String[] tokens) {
152 | for (final String token : tokens) {
153 | addToken(token, updateTokens);
154 | }
155 | }
156 |
157 | public void addDeleteTokens(final String[] tokens) {
158 | for (final String token : tokens) {
159 | addToken(token, deleteTokens);
160 | }
161 | }
162 |
163 | public void addUpdateToken(final String token) {
164 | addToken(token, updateTokens);
165 | }
166 |
167 | public void addDeleteToken(final String token) {
168 | addToken(token, deleteTokens);
169 | }
170 |
171 | private void addToken(final String token, final List list) {
172 | if (token == null || token.trim().isEmpty() || token.contains(",")) {
173 | throw new IllegalArgumentException("'" + token
174 | + "' is not a valid dls token");
175 | }
176 | list.add(token.trim());
177 | }
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/service/permission/PermEvaluator.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.service.permission;
2 |
3 | import java.net.InetAddress;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | import org.elasticsearch.common.logging.ESLogger;
10 | import org.elasticsearch.common.logging.Loggers;
11 | import org.elasticsearch.common.xcontent.XContentFactory;
12 | import org.elasticsearch.common.xcontent.XContentParser;
13 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
14 |
15 | public abstract class PermEvaluator {
16 |
17 | protected static final ESLogger log = Loggers
18 | .getLogger(PermEvaluator.class);
19 | protected final String xSecurityConfiguration;
20 | protected XContentParser parser = null;
21 |
22 | protected PermEvaluator(final String xSecurityConfiguration) {
23 | super();
24 |
25 | if (xSecurityConfiguration == null || xSecurityConfiguration.isEmpty()) {
26 | throw new IllegalArgumentException(
27 | "securityconfiguration must not be null or empty");
28 | }
29 |
30 | this.xSecurityConfiguration = xSecurityConfiguration;
31 |
32 | // log.debug("Configuration: " + xSecurityConfiguration);
33 | }
34 |
35 | protected abstract T createFromString(String s);
36 |
37 | protected abstract T getDefaultPermLevelForEvaluator();
38 |
39 | protected abstract String getPermissionFieldName();
40 |
41 | public T evaluatePerm(final List indices, final List types,
42 | final InetAddress hostAddress, final UserRoleCallback callback)
43 | throws MalformedConfigurationException {
44 |
45 | /*if(indices==null || types == null || hostAddress == null) {
46 | throw new MalformedConfigurationException("Indices, types and hostAddress must not be null");
47 | }*/
48 |
49 | final List> perms = new ArrayList>();
50 |
51 | //final List matchList = new ArrayList();
52 |
53 | try {
54 |
55 | this.parser = XContentFactory.xContent(this.xSecurityConfiguration)
56 | .createParser(this.xSecurityConfiguration);
57 |
58 | final String permissionFieldName = this.getPermissionFieldName();
59 |
60 | XContentParser.Token token = null;
61 | String currentFieldName = null;
62 | Perm currentPerm = null;
63 | while ((token = this.parser.nextToken()) != null) {
64 |
65 | if (token == XContentParser.Token.START_OBJECT) {
66 | currentPerm = new Perm();
67 |
68 | } else if (token == XContentParser.Token.END_OBJECT) {
69 |
70 | if (currentPerm != null && perms.contains(currentPerm)) {
71 | log.error("Duplicate permissions " + currentPerm);
72 | throw new MalformedConfigurationException(
73 | "Duplicate permissions found");
74 | }
75 |
76 | /*if (currentPerm != null && !currentPerm.isValid()) {
77 | log.error("Perm not valid " + currentPerm);
78 | throw new MalformedConfigurationException(
79 | "Invalid permission found");
80 | }*/
81 |
82 | if (currentPerm != null) {
83 |
84 | if(currentPerm.permLevel == null){
85 | currentPerm.permLevel = getDefaultPermLevelForEvaluator();
86 | }
87 |
88 | perms.add(currentPerm);
89 | currentPerm = null;
90 | }
91 |
92 | } else if (token == XContentParser.Token.FIELD_NAME) {
93 | currentFieldName = this.parser.currentName();
94 |
95 | } else if (token.isValue()) {
96 |
97 | if ("hosts".equals(currentFieldName)) {
98 | currentPerm.addInetAddress(this.parser.text());
99 | }
100 | if ("users".equals(currentFieldName)) {
101 | currentPerm.addUser(this.parser.text());
102 | }
103 | if ("roles".equals(currentFieldName)) {
104 | currentPerm.addRole(this.parser.text());
105 | } else if ("indices".equals(currentFieldName)) {
106 | currentPerm.addIndice(this.parser.text());
107 | } else if ("types".equals(currentFieldName)) {
108 | currentPerm.addType(this.parser.text());
109 | } else if (permissionFieldName.equals(currentFieldName)) {
110 | final String text = this.parser.text();
111 | currentPerm.setPermLevel(this
112 | .createFromString(text == null ? null : text
113 | .trim()));
114 | }
115 |
116 | }
117 |
118 | }
119 |
120 | } catch (final Exception e) {
121 | throw new MalformedConfigurationException(e);
122 | } finally {
123 | this.parser.close();
124 | }
125 |
126 |
127 |
128 |
129 |
130 |
131 | log.debug("Checking " + perms.size() + " perms");
132 |
133 | T permLevel = null;
134 |
135 | for (final Perm p : perms) {
136 |
137 | if (p.isDefault()) {
138 | permLevel = p.permLevel;
139 | if (log.isDebugEnabled()) {
140 | log.debug("Default set to " + permLevel);
141 | }
142 | break;
143 | }
144 | }
145 |
146 | if (permLevel == null) {
147 | throw new MalformedConfigurationException(
148 | "No default configuration found");
149 | }
150 |
151 | /*for (final Perm p : perms) {
152 |
153 | for (final String ip : p.inetAddresses) {
154 | //matchList.add(new WildcardString(ip));
155 | }
156 | }*/
157 |
158 | final String clientHostName = hostAddress.getHostName();
159 | final String clientHostIp = hostAddress.getHostAddress();
160 |
161 | permloop: for (final Perm p : perms) {
162 |
163 | if (p.isDefault()) {
164 | continue;
165 | }
166 |
167 | String _role = null;
168 | String _host = null;
169 |
170 | log.debug("Check perm " + p);
171 |
172 | // TODO difference between not here and []
173 | if (!p.users.isEmpty()
174 | && !p.users.contains("*")
175 | && (callback == null || callback.getRemoteuser() == null || !p.users
176 | .contains(callback.getRemoteuser()))) {
177 | if(callback != null) {
178 | log.debug("User " + callback.getRemoteuser()
179 | + " does not match, so skip this permission");
180 | } else {
181 | log.debug("No callback");
182 | }
183 | continue permloop;
184 | }
185 |
186 | log.debug("User "
187 | + (callback == null ? "" : callback.getRemoteuser())
188 | + " match");
189 |
190 | if (!p.roles.contains("*") && !p.roles.isEmpty()) {
191 | if (callback == null) {
192 | log.debug("Role does not match, so skip this permission");
193 | continue permloop;
194 | }
195 |
196 | for (final String role : p.roles) {
197 | if (callback.isRemoteUserInRole(role)) {
198 | log.debug("Role " + role + " match");
199 | _role = role;
200 | break;
201 | }
202 | }
203 |
204 | if (_role == null) {
205 | log.debug("Role does not match, so skip this permission");
206 | continue permloop;
207 | }
208 | }
209 |
210 | if (!p.inetAddresses.contains("*") && !p.inetAddresses.isEmpty()) {
211 | for (final String pinetAddress : p.inetAddresses) {
212 | if (isWildcardMatch(pinetAddress, clientHostName)
213 | || isWildcardMatch(pinetAddress, clientHostIp)) {
214 |
215 | log.debug("Host adress " + pinetAddress + " match");
216 | _host = pinetAddress;
217 | break;
218 |
219 | }
220 |
221 | }
222 |
223 | if (_host == null) {
224 |
225 | log.debug("Host adress ("
226 | + clientHostIp
227 | + "(ip) and "
228 | + clientHostName
229 | + " (hostname) does not match, so skip this permission");
230 | continue permloop;
231 |
232 | }
233 |
234 | }
235 |
236 | if (!p.types.isEmpty() && !p.types.contains("*")) {
237 |
238 | boolean typeMatch=false;
239 |
240 | typeloop:
241 | for (final String pType : p.types) {
242 |
243 | for (final String tType : types)
244 | {
245 | if (isWildcardMatch(tType, pType)) {
246 | log.debug("Type "+pType+" match " + tType + "");
247 | typeMatch=true;
248 | break typeloop;
249 |
250 | }else {
251 | log.debug("Type "+pType+" not match " + tType + "");
252 | }
253 |
254 | }
255 | }
256 |
257 | if(!typeMatch){
258 | log.debug("No type matches, so skip this permission ["
259 | + p.types + " != " + types + "]");
260 | continue permloop;
261 | }
262 | }
263 |
264 | log.debug("All types matches");
265 |
266 | if ( !p.indices.isEmpty() && !p.indices.contains("*")) {
267 |
268 |
269 | boolean indexMatch=false;
270 |
271 | indexloop:
272 | for (final String pIndex : p.indices) {
273 |
274 | if(indices != null) {
275 | for (final String tIndex : indices)
276 | {
277 | if (isWildcardMatch(tIndex, pIndex)) {
278 | log.debug("Index "+pIndex+" match " + tIndex + "");
279 | indexMatch=true;
280 | break indexloop;
281 |
282 | }else {
283 | log.debug("Index "+pIndex+" not match " + tIndex + "");
284 | }
285 |
286 | }
287 | }
288 |
289 | }
290 |
291 | if(!indexMatch)
292 | {
293 |
294 | log.debug("No index matches, so skip this permission ["
295 | + p.indices + " != " + indices + "]");
296 | continue permloop;
297 | }
298 |
299 |
300 | }
301 |
302 |
303 | //START
304 | //added condition to check if indices provided are empty to validate the matching of index. This is required to allow requesting metadata queries like /_mapping, /_setting etc.
305 | //(contributed by Ram Kotamaraja)
306 | else
307 | if((indices == null || indices.isEmpty()) && !p.indices.isEmpty() && !p.indices.contains("*") ){
308 |
309 | log.debug("Not all indexes match because no index specified, so skip this permission ["
310 | + p.indices + " != " + indices + "]");
311 | continue permloop;
312 |
313 | }
314 | //END
315 |
316 | log.debug("All rules match, will apply " + p);
317 | return p.permLevel;
318 |
319 | }// end permloop
320 |
321 | log.debug("No rules matched, will apply default perm " + permLevel);
322 | return permLevel;
323 |
324 | }
325 |
326 | protected static class Perm {
327 |
328 | private final List inetAddresses = new ArrayList();
329 | private final List users = new ArrayList();
330 | private final List roles = new ArrayList();
331 | private final List indices = new ArrayList();
332 | private final List types = new ArrayList();
333 |
334 | private T permLevel = null;
335 |
336 | public boolean isValid() {
337 | return this.permLevel != null;
338 | }
339 |
340 | // default is either all props empty and/or "*"
341 | public boolean isDefault() {
342 |
343 | if (this.inetAddresses.isEmpty() && this.users.isEmpty()
344 | && this.roles.isEmpty() && this.indices.isEmpty()
345 | && this.types.isEmpty()) {
346 | return true;
347 | }
348 |
349 | return (this.inetAddresses.isEmpty() ? true : this.inetAddresses
350 | .size() == 1 && "*".equals(this.inetAddresses.get(0)))
351 | && (this.users.isEmpty() ? true : this.users.size() == 1
352 | && "*".equals(this.users.get(0)))
353 | && (this.roles.isEmpty() ? true : this.roles.size() == 1
354 | && "*".equals(this.roles.get(0)))
355 | && (this.types.isEmpty() ? true : this.types.size() == 1
356 | && "*".equals(this.types.get(0)))
357 | && (this.indices.isEmpty() ? true
358 | : this.indices.size() == 1
359 | && "*".equals(this.indices.get(0)));
360 | }
361 |
362 | public void addInetAddress(final String inetAddress) {
363 | if (inetAddress == null || inetAddress.isEmpty()
364 | || inetAddress.contains(",")) {
365 | throw new IllegalArgumentException("'" + inetAddress
366 | + "' is not a valid inet address");
367 | }
368 | this.inetAddresses.add(inetAddress.trim());
369 | }
370 |
371 | public void addIndice(final String indice) {
372 | if (indice == null || indice.isEmpty() || indice.contains(",")) {
373 | throw new IllegalArgumentException("'" + indice
374 | + "' is not a valid index name");
375 | }
376 | this.indices.add(indice.trim());
377 | }
378 |
379 | public void addUser(final String user) {
380 | if (user == null || user.isEmpty() || user.contains(",")) {
381 | throw new IllegalArgumentException("'" + user
382 | + "' is not a valid user");
383 | }
384 | this.users.add(user.trim());
385 | }
386 |
387 | public void addRole(final String role) {
388 | if (role == null || role.isEmpty() || role.contains(",")) {
389 | throw new IllegalArgumentException("'" + role
390 | + "' is not a valid role");
391 | }
392 | this.roles.add(role.trim());
393 | }
394 |
395 | public void addType(final String type) {
396 | if (type == null || type.isEmpty() || type.contains(",")) {
397 | throw new IllegalArgumentException("'" + type
398 | + "' is not a valid type");
399 | }
400 | this.types.add(type.trim());
401 | }
402 |
403 | public void setPermLevel(final T permLevel) {
404 |
405 | if (permLevel == null) {
406 | throw new IllegalArgumentException("'" + permLevel
407 | + "' is not a valid permLevel");
408 | }
409 |
410 | this.permLevel = permLevel;
411 | }
412 |
413 | public Perm() {
414 |
415 | }
416 |
417 | @Override
418 | public int hashCode() {
419 | final int prime = 31;
420 | int result = 1;
421 | result = prime * result
422 | + (this.indices == null ? 0 : this.indices.hashCode());
423 | result = prime
424 | * result
425 | + (this.inetAddresses == null ? 0 : this.inetAddresses
426 | .hashCode());
427 | result = prime * result
428 | + (this.roles == null ? 0 : this.roles.hashCode());
429 | result = prime * result
430 | + (this.types == null ? 0 : this.types.hashCode());
431 | result = prime * result
432 | + (this.users == null ? 0 : this.users.hashCode());
433 | return result;
434 | }
435 |
436 | @Override
437 | public boolean equals(final Object obj) {
438 | if (this == obj) {
439 | // log.debug("perm ==");
440 | return true;
441 | }
442 | if (obj == null) {
443 | // log.debug("perm other null");
444 | return false;
445 | }
446 | if (this.getClass() != obj.getClass()) {
447 | // log.debug("perm class mismatch");
448 | return false;
449 | }
450 | final Perm> other = (Perm>) obj;
451 | if (this.indices == null) {
452 | if (other.indices != null) {
453 | return false;
454 | }
455 | } else if (!equalLists(this.indices, other.indices)) {
456 | // log.debug("perm list not match: indices");
457 | return false;
458 | }
459 | if (this.inetAddresses == null) {
460 | if (other.inetAddresses != null) {
461 | return false;
462 | }
463 | } else if (!equalLists(this.inetAddresses, other.inetAddresses)) {
464 | // log.debug("perm list not match: inetaddr");
465 | return false;
466 | }
467 | if (this.roles == null) {
468 | if (other.roles != null) {
469 | return false;
470 | }
471 | } else if (!equalLists(this.roles, other.roles)) {
472 | // log.debug("perm list not match: roles");
473 | return false;
474 | }
475 | if (this.users == null) {
476 | if (other.users != null) {
477 | return false;
478 | }
479 | } else if (!equalLists(this.users, other.users)) {
480 | // log.debug("perm list not match: users");
481 | return false;
482 | }
483 |
484 | if (this.types == null) {
485 | if (other.types != null) {
486 | return false;
487 | }
488 | } else if (!equalLists(this.types, other.types)) {
489 | // log.debug("perm list not match: types");
490 | return false;
491 | }
492 |
493 | return true;
494 | }
495 |
496 | @Override
497 | public String toString() {
498 | return "Perm [inetAddresses=" + this.inetAddresses + ", users="
499 | + this.users + ", roles=" + this.roles + ", indices="
500 | + this.indices + ", types=" + this.types + ", permLevel="
501 | + this.permLevel + ", isValid()=" + this.isValid()
502 | + ", isDefault()=" + this.isDefault() + "]";
503 | }
504 |
505 | }
506 |
507 | private static boolean equalLists(final List one,
508 | final List two) {
509 | if (one == null && two == null) {
510 | return true;
511 | }
512 |
513 | if (one == null && two != null || one != null && two == null
514 | || one.size() != two.size()) {
515 | return false;
516 | }
517 |
518 | return one.containsAll(two) && two.containsAll(one);
519 | }
520 |
521 |
522 | private boolean isWildcardMatch(String a, String b) {
523 |
524 | String escapedA = a.replace(".", "\\.").replace("*",
525 | ".*");
526 |
527 | Pattern p = Pattern.compile(escapedA);
528 | Matcher m = p.matcher(b);
529 | if(m.matches()){
530 | return true;
531 | } else {
532 | String escapedB = b.replace(".", "\\.").replace("*",
533 | ".*");
534 |
535 | p = Pattern.compile(escapedB);
536 | m = p.matcher(a);
537 | return m.matches();
538 | }
539 | }
540 |
541 | }
542 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/service/permission/UserRoleCallback.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.service.permission;
2 |
3 | public interface UserRoleCallback {
4 |
5 | public String getRemoteuser();
6 |
7 | public boolean isRemoteUserInRole(String role);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/util/EditableRestRequest.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.util;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.Map.Entry;
6 |
7 | import org.elasticsearch.common.bytes.BytesReference;
8 | import org.elasticsearch.rest.RestRequest;
9 |
10 |
11 | public class EditableRestRequest extends RestRequest {
12 |
13 | private RestRequest innerRestquest = null;
14 | private BytesReference content = null;
15 | private Map params = null;
16 | private Method method = null;
17 | private String uri = null;
18 | private String rawPath = null;
19 | private boolean hasContent;
20 | private boolean contentUnsafe;
21 |
22 | public EditableRestRequest(final RestRequest innerRestquest) {
23 |
24 | this.innerRestquest = innerRestquest;
25 | content = innerRestquest.content();
26 | params = innerRestquest.params();
27 | method = innerRestquest.method();
28 | uri = innerRestquest.uri();
29 | rawPath = innerRestquest.rawPath();
30 | hasContent = innerRestquest.hasContent();
31 | contentUnsafe = innerRestquest.contentUnsafe();
32 |
33 | }
34 |
35 | public void addParam(String key, String value){
36 | if(params==null){
37 | params=new HashMap();
38 | }
39 | params.put(key, value);
40 | }
41 |
42 | public void setContent(final BytesReference content) {
43 | this.content = content;
44 | }
45 |
46 | public void setParams(final Map params) {
47 | this.params = params;
48 | }
49 |
50 | public void setMethod(final Method method) {
51 | this.method = method;
52 | }
53 |
54 | public void setUri(final String uri) {
55 | this.uri = uri;
56 | }
57 |
58 | public void setRawPath(final String rawPath) {
59 | this.rawPath = rawPath;
60 | }
61 |
62 | public void setHasContent(final boolean hasContent) {
63 | this.hasContent = hasContent;
64 | }
65 |
66 | public void setContentUnsafe(final boolean contentUnsafe) {
67 | this.contentUnsafe = contentUnsafe;
68 | }
69 |
70 | @Override
71 | public Method method() {
72 | return method;
73 | }
74 |
75 | @Override
76 | public String uri() {
77 | return uri;
78 | }
79 |
80 | @Override
81 | public String rawPath() {
82 |
83 | return rawPath;
84 | }
85 |
86 | @Override
87 | public boolean hasContent() {
88 |
89 | return hasContent;
90 | }
91 |
92 | @Override
93 | public boolean contentUnsafe() {
94 |
95 | return contentUnsafe;
96 | }
97 |
98 | @Override
99 | public BytesReference content() {
100 |
101 | return content;
102 | }
103 |
104 | @Override
105 | public String header(final String name) {
106 |
107 | return innerRestquest.header(name);
108 | }
109 |
110 | @Override
111 | public boolean hasParam(final String key) {
112 |
113 | return params.containsKey(key);
114 | }
115 |
116 | @Override
117 | public String param(final String key) {
118 |
119 | return params.get(key);
120 | }
121 |
122 | @Override
123 | public Map params() {
124 |
125 | return params;
126 | }
127 |
128 | @Override
129 | public String param(final String key, final String defaultValue) {
130 | final String value = params.get(key);
131 | if (value == null) {
132 | return defaultValue;
133 | }
134 | return value;
135 | }
136 |
137 | @Override
138 | public Iterable> headers() {
139 | return innerRestquest.headers();
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/src/main/java/org/elasticsearch/plugins/security/util/SecurityUtil.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.util;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.UnsupportedEncodingException;
6 | import java.net.URL;
7 | import java.net.URLDecoder;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | import org.elasticsearch.common.Strings;
12 | import org.elasticsearch.common.logging.ESLogger;
13 | import org.elasticsearch.common.logging.Loggers;
14 | import org.elasticsearch.common.xcontent.XContentBuilder;
15 | import org.elasticsearch.common.xcontent.XContentFactory;
16 | import org.elasticsearch.common.xcontent.XContentHelper;
17 | import org.elasticsearch.common.xcontent.XContentType;
18 | import org.elasticsearch.rest.BytesRestResponse;
19 | import org.elasticsearch.rest.RestChannel;
20 | import org.elasticsearch.rest.RestRequest;
21 | import org.elasticsearch.rest.RestRequest.Method;
22 | import org.elasticsearch.rest.RestResponse;
23 | import org.elasticsearch.rest.RestStatus;
24 |
25 | public class SecurityUtil {
26 |
27 | private static final ESLogger log = Loggers.getLogger(SecurityUtil.class);
28 |
29 | private SecurityUtil() {
30 |
31 | }
32 |
33 | public static File getAbsoluteFilePathFromClassPath(
34 | final String fileNameFromClasspath) {
35 |
36 | File jaasConfigFile = null;
37 | final URL jaasConfigURL = SecurityUtil.class.getClassLoader()
38 | .getResource(fileNameFromClasspath);
39 | if (jaasConfigURL != null) {
40 | try {
41 | jaasConfigFile = new File(URLDecoder.decode(
42 | jaasConfigURL.getFile(), "UTF-8"));
43 | } catch (final UnsupportedEncodingException e) {
44 | return null;
45 | }
46 |
47 | if (jaasConfigFile.exists() && jaasConfigFile.canRead()) {
48 | return jaasConfigFile;
49 | } else {
50 | log.error(
51 | "Cannot read from {}, maybe the file does not exists? ",
52 | jaasConfigFile.getAbsolutePath());
53 | }
54 |
55 | } else {
56 | log.error("Failed to load " + fileNameFromClasspath);
57 | }
58 |
59 | return null;
60 |
61 | }
62 |
63 | public static boolean setSystemPropertyToAbsoluteFilePathFromClassPath(
64 | final String property, final String fileNameFromClasspath) {
65 | if (System.getProperty(property) == null) {
66 | File jaasConfigFile = null;
67 | final URL jaasConfigURL = SecurityUtil.class.getClassLoader()
68 | .getResource(fileNameFromClasspath);
69 | if (jaasConfigURL != null) {
70 | try {
71 | jaasConfigFile = new File(URLDecoder.decode(
72 | jaasConfigURL.getFile(), "UTF-8"));
73 | } catch (final UnsupportedEncodingException e) {
74 | return false;
75 | }
76 |
77 | if (jaasConfigFile.exists() && jaasConfigFile.canRead()) {
78 | System.setProperty(property,
79 | jaasConfigFile.getAbsolutePath());
80 |
81 | log.info("Load " + fileNameFromClasspath + " from {} ",
82 | jaasConfigFile.getAbsolutePath());
83 | return true;
84 | } else {
85 | log.error(
86 | "Cannot read from {}, maybe the file does not exists? ",
87 | jaasConfigFile.getAbsolutePath());
88 | }
89 |
90 | } else {
91 | log.error("Failed to load " + fileNameFromClasspath);
92 | }
93 | } else {
94 | log.warn("Property " + property + " already set to "
95 | + System.getProperty(property));
96 | }
97 |
98 | return false;
99 | }
100 |
101 | public static boolean setSystemPropertyToAbsoluteFile(
102 | final String property, final String fileName) {
103 | if (System.getProperty(property) == null) {
104 |
105 | if (fileName == null) {
106 | log.error("Cannot set property " + property
107 | + " because filename is null");
108 |
109 | return false;
110 | }
111 |
112 | final File jaasConfigFile = new File(fileName).getAbsoluteFile();
113 |
114 | if (jaasConfigFile.exists() && jaasConfigFile.canRead()) {
115 | System.setProperty(property, jaasConfigFile.getAbsolutePath());
116 |
117 | log.info("Load " + fileName + " from {} ",
118 | jaasConfigFile.getAbsolutePath());
119 | return true;
120 | } else {
121 | log.error(
122 | "Cannot read from {}, maybe the file does not exists? ",
123 | jaasConfigFile.getAbsolutePath());
124 | }
125 |
126 | } else {
127 | log.warn("Property " + property + " already set to "
128 | + System.getProperty(property));
129 | }
130 |
131 | return false;
132 | }
133 |
134 | public static List getIndices(final RestRequest request) {
135 | String[] indices = new String[0];
136 | final String path = request.path();
137 | // TODO all indices , length=0
138 | log.debug("Evaluate decoded path for indices'" + path + "'");
139 |
140 | if (!path.startsWith("/")) {
141 |
142 | return null;
143 | }
144 |
145 | if (path.length() > 1) {
146 |
147 | int endIndex;
148 |
149 |
150 |
151 |
152 | /* if ((endIndex = path.indexOf('/', 1)) != -1) {
153 | indices = Strings.splitStringByCommaToArray(path.substring(1,
154 | endIndex));
155 |
156 | }
157 | */
158 | /**
159 | * (contributed by Ram Kotamaraja)
160 | *The above commented code handles code if there is a '/' at the end of the elastic search indices. Code is modified to handle indices where there is no '/' after it.
161 | *Code below also handles the root level queries like '/_mapping', '/_settings' etc.
162 | */
163 |
164 | //Code modification START - Ram Kotamaraja
165 | if ((path.indexOf('/', 1)) != -1) {
166 | endIndex = path.indexOf('/', 1);
167 | }else{
168 | endIndex = path.length();
169 | }
170 |
171 | //check if the index start with /_. If it is not staring, then parse path, if not do nothing to return empty object
172 | if (!path.trim().startsWith("/_")) {
173 | indices = Strings.splitStringByCommaToArray(path.substring(1,endIndex));
174 | }
175 |
176 | //Code modification END - Ram Kotamaraja
177 |
178 |
179 |
180 |
181 | }
182 |
183 | log.debug("Indices: " + Arrays.toString(indices));
184 | return Arrays.asList(indices);
185 |
186 | }
187 |
188 | public static String getId(final RestRequest request) {
189 |
190 | String id = null;
191 | final String path = request.path();
192 |
193 | log.debug("Evaluate decoded path for id '" + path + "'");
194 |
195 | if (!path.startsWith("/")) {
196 |
197 | return null;
198 | }
199 |
200 | if (path.length() > 1) {
201 |
202 | int endIndex;
203 |
204 | if ((endIndex = path.lastIndexOf('/')) != -1) {
205 | id = path.substring(endIndex + 1);
206 |
207 | if (id.contains("?")) {
208 | id = path.substring(id.indexOf("?") + 1);
209 |
210 | }
211 |
212 | // if(id.contains("/")) return null;
213 |
214 | }
215 | }
216 |
217 | log.debug("Id: " + id);
218 | return id;
219 |
220 | }
221 |
222 | public static List getTypes(final RestRequest request) {
223 | String[] types = new String[0];
224 | final String path = request.path();
225 |
226 | // TODO all types, length=0 or _all ??
227 | // TODO aliases indices get expanded before or after rest layer?
228 | log.debug("Evaluate decoded path for types '" + path + "'");
229 |
230 | if (!path.startsWith("/")) {
231 |
232 | return null;
233 | }
234 |
235 | if (path.length() > 1) {
236 |
237 | int endIndex;
238 |
239 | if ((endIndex = path.indexOf('/', 1)) != -1) {
240 |
241 | int endType;
242 |
243 | if ((endType = path.indexOf('/', endIndex + 1)) != -1) {
244 |
245 | types = Strings.splitStringByCommaToArray(path.substring(
246 | endIndex + 1, endType));
247 | }
248 |
249 | }
250 | }
251 |
252 | log.debug("Types: " + Arrays.toString(types));
253 | return Arrays.asList(types);
254 |
255 | }
256 |
257 | public static void send(final RestRequest request,
258 | final RestChannel channel, final RestStatus status, final String arg) {
259 | try {
260 |
261 | final XContentBuilder builder = channel.newBuilder();
262 |
263 | builder.startObject();
264 | builder.field("status", status.getStatus());
265 |
266 | if (arg != null && !arg.isEmpty()) {
267 | builder.field("message", arg);
268 | }
269 |
270 | builder.endObject();
271 | channel.sendResponse(new BytesRestResponse(status, builder));
272 | } catch (final Exception e) {
273 | log.error("Failed to send a response.", e);
274 | try {
275 | channel.sendResponse(new BytesRestResponse(channel,
276 | e));
277 | } catch (final IOException e1) {
278 | log.error("Failed to send a failure response.", e1);
279 | }
280 | }
281 | }
282 |
283 |
284 | public static String[] BUILT_IN_ADMIN_COMMANDS = new String[] { "_cluster",
285 | "_settings", "_close", "_open", "_template", "_status", "_stats",
286 | "_segments", "_cache", "_gateway", "_optimize", "_flush",
287 | "_warmer", "_refresh", "_shutdown"};
288 |
289 | public static String[] BUILT_IN_WRITE_COMMANDS_STRICT = new String[] { "_create",
290 | "_update", "_bulk", "_percolator","_mapping", "_aliases", "_analyze"};
291 |
292 | public static String[] BUILT_IN_READ_COMMANDS_STRICT = new String[] { "_search",
293 | "_msearch","_mlt", "_explain", "_validate","_count","_suggest", "_percolate", "_nodes"};
294 |
295 |
296 | public static String[] BUILT_IN_WRITE_COMMANDS_LAX = new String[] { "_create",
297 | "_update", "_bulk"};
298 |
299 | public static String[] BUILT_IN_READ_COMMANDS_LAX = new String[] { "_search",
300 | "_msearch","_mlt", "_explain", "_validate","_count","_suggest", "_percolate", "_nodes", "_percolator","_mapping", "_aliases", "_analyze"};
301 |
302 | private static boolean stringContainsItemFromListAsCommand(
303 | final String inputString, final String[] items) {
304 |
305 | for (int i = 0; i < items.length; i++) {
306 | if (inputString.contains("/" + items[i])
307 | && !inputString.contains(items[i] + "/")) {
308 |
309 | return true;
310 | }
311 | }
312 |
313 | return false;
314 | }
315 |
316 | public static boolean stringContainsItemFromListAsTypeOrIndex(
317 | final String inputString, final String[] items) {
318 | for (int i = 0; i < items.length; i++) {
319 | if (inputString.contains("/" + items[i] + "/")) {
320 | return true;
321 | }
322 | }
323 | return false;
324 | }
325 |
326 | public static boolean isWriteRequest(final RestRequest request, boolean strictModeEnabled) {
327 | if (request.method() == Method.DELETE || request.method() == Method.PUT) {
328 | return true;
329 | }
330 |
331 | if (request.method() == Method.POST) {
332 | if (!stringContainsItemFromListAsCommand(request.path(),
333 | strictModeEnabled?SecurityUtil.BUILT_IN_READ_COMMANDS_STRICT : SecurityUtil.BUILT_IN_READ_COMMANDS_LAX)) {
334 | return true;
335 | }
336 | }
337 |
338 | return stringContainsItemFromListAsCommand(request.path(),
339 | strictModeEnabled?SecurityUtil.BUILT_IN_WRITE_COMMANDS_STRICT : SecurityUtil.BUILT_IN_WRITE_COMMANDS_LAX);
340 | }
341 |
342 | public static boolean isAdminRequest(final RestRequest request) {
343 | return stringContainsItemFromListAsCommand(request.path(),
344 | BUILT_IN_ADMIN_COMMANDS);
345 | }
346 |
347 | public static boolean isReadRequest(final RestRequest request, boolean strictModeEnabled) {
348 | return !isWriteRequest(request, strictModeEnabled) && !isAdminRequest(request);
349 | }
350 |
351 | public static XContentType xContentTypefromRestContentType(String contentType) {
352 | if (contentType == null) {
353 | return null;
354 | }
355 |
356 | contentType = contentType.trim();
357 |
358 | if (contentType.startsWith("application/json") || contentType.startsWith("json")) {
359 | return XContentType.JSON;
360 | }
361 |
362 | if (contentType.startsWith("application/smile") || contentType.startsWith("smile")) {
363 | return XContentType.SMILE;
364 | }
365 |
366 | if (contentType.startsWith("application/yaml") || contentType.startsWith("yaml")) {
367 | return XContentType.YAML;
368 | }
369 |
370 | if (contentType.startsWith("application/cbor") || contentType.startsWith("cbor")) {
371 | return XContentType.CBOR;
372 | }
373 |
374 | return null;
375 | }
376 | }
377 |
--------------------------------------------------------------------------------
/src/main/resources/es-plugin.properties:
--------------------------------------------------------------------------------
1 | plugin=org.elasticsearch.plugins.security.SecurityPlugin
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/AbstractUnitTest.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import static com.github.tlrx.elasticsearch.test.EsSetup.createIndex;
4 | import static com.github.tlrx.elasticsearch.test.EsSetup.deleteAll;
5 | import io.searchbox.client.JestClient;
6 | import io.searchbox.client.JestClientFactory;
7 | import io.searchbox.client.JestResult;
8 | import io.searchbox.client.config.HttpClientConfig;
9 | import io.searchbox.client.http.JestHttpClient;
10 | import io.searchbox.core.Get;
11 | import io.searchbox.core.Index;
12 | import io.searchbox.core.Search;
13 |
14 | import java.io.FileInputStream;
15 | import java.io.IOException;
16 | import java.io.StringWriter;
17 | import java.net.URL;
18 | import java.security.KeyStore;
19 | import java.security.PrivilegedExceptionAction;
20 | import java.util.ArrayList;
21 | import java.util.HashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.Properties;
25 |
26 | import javax.net.ssl.SSLContext;
27 | import javax.security.auth.Subject;
28 | import javax.security.auth.callback.Callback;
29 | import javax.security.auth.callback.CallbackHandler;
30 | import javax.security.auth.callback.NameCallback;
31 | import javax.security.auth.callback.PasswordCallback;
32 | import javax.security.auth.login.LoginContext;
33 |
34 | import org.apache.commons.io.IOUtils;
35 | import org.apache.http.Header;
36 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
37 | import org.apache.http.conn.ssl.SSLContexts;
38 | import org.apache.http.impl.client.HttpClientBuilder;
39 | import org.apache.http.impl.client.HttpClients;
40 | import org.apache.http.message.BasicHeader;
41 | import org.elasticsearch.common.logging.ESLogger;
42 | import org.elasticsearch.common.logging.Loggers;
43 | import org.elasticsearch.common.settings.ImmutableSettings;
44 | import org.elasticsearch.common.settings.ImmutableSettings.Builder;
45 | import org.elasticsearch.plugins.security.util.SecurityUtil;
46 | import org.ietf.jgss.GSSContext;
47 | import org.ietf.jgss.GSSCredential;
48 | import org.ietf.jgss.GSSException;
49 | import org.ietf.jgss.GSSManager;
50 | import org.ietf.jgss.GSSName;
51 | import org.ietf.jgss.Oid;
52 | import org.junit.After;
53 | import org.junit.Assert;
54 | import org.junit.Before;
55 | import org.junit.Rule;
56 | import org.junit.rules.TestName;
57 | import org.junit.rules.TestWatcher;
58 | import org.junit.runner.Description;
59 |
60 | import com.github.tlrx.elasticsearch.test.EsSetup;
61 |
62 | public abstract class AbstractUnitTest {
63 |
64 | @Rule
65 | public TestName name = new TestName();
66 | private JestClient client;
67 | protected final Builder settingsBuilder;
68 | protected Map headers = new HashMap();
69 |
70 |
71 | @Rule
72 | public TestWatcher testWatcher = new TestWatcher() {
73 | @Override
74 | protected void starting(final Description description) {
75 | String methodName = description.getMethodName();
76 | String className = description.getClassName();
77 | className = className.substring(className.lastIndexOf('.') + 1);
78 | System.out.println("Starting JUnit-test: " + className + " " + methodName);
79 | }
80 | };
81 |
82 | protected AbstractUnitTest() {
83 | super();
84 |
85 |
86 |
87 | settingsBuilder = ImmutableSettings
88 | .settingsBuilder()
89 | // .put(NODE_NAME, elasticsearchNode.name())
90 | // .put("node.data", elasticsearchNode.data())
91 | // .put("cluster.name", elasticsearchNode.clusterName())
92 | .put("index.store.type", "memory")
93 | .put("index.store.fs.memory.enabled", "true")
94 | .put("gateway.type", "none")
95 | .put("path.data", "target/data")
96 | .put("path.work", "target/work")
97 | .put("path.logs", "target/logs")
98 | .put("path.conf", "target/config")
99 | .put("path.plugins", "target/plugins")
100 | .put("index.number_of_shards", "1")
101 | .put("index.number_of_replicas", "0")
102 | .put(getProperties())
103 | .put("http.type",
104 | "org.elasticsearch.plugins.security.http.tomcat.TomcatHttpServerTransport");
105 |
106 | }
107 |
108 | protected Properties getProperties() {
109 | return new Properties();
110 | }
111 |
112 | protected final ESLogger log = Loggers.getLogger(this.getClass());
113 |
114 |
115 | protected String getServerUri() {
116 | return "http"+(isSSL()?"s":"")+"://localhost:8080";
117 | }
118 |
119 | protected boolean isSSL() {
120 | return false;
121 | }
122 |
123 | protected String loadFile(final String file) throws IOException {
124 |
125 | final StringWriter sw = new StringWriter();
126 | IOUtils.copy(this.getClass().getResourceAsStream("/" + file), sw);
127 | return sw.toString();
128 |
129 | }
130 |
131 | EsSetup esSetup;
132 |
133 | @Before
134 | public void setUp() throws Exception {
135 |
136 | headers.clear();
137 |
138 | // Instantiates a local node & client
139 |
140 | esSetup = new EsSetup(settingsBuilder.build());
141 |
142 | // Clean all, and creates some indices
143 |
144 | esSetup.execute(
145 |
146 | deleteAll(),
147 |
148 | createIndex("my_index_1")/*
149 | * ,
150 | *
151 | * createIndex("my_index_2")
152 | *
153 | * .withSettings(fromClassPath(
154 | * "path/to/settings.json"))
155 | *
156 | * .withMapping("type1",
157 | * fromClassPath("path/to/mapping/of/type1.json"
158 | * ))
159 | *
160 | * .withData(fromClassPath("path/to/bulk.json"))
161 | */
162 |
163 | );
164 |
165 |
166 | }
167 |
168 | @After
169 | public void tearDown() throws Exception {
170 |
171 | // This will stop and clean the local node
172 |
173 | if(esSetup != null) {
174 | esSetup.terminate();
175 | }
176 |
177 | if(client != null) {
178 | client.shutdownClient();
179 | }
180 |
181 | }
182 |
183 |
184 |
185 | protected JestResult executeIndex(final String file, final String index,
186 | final String type, final String id, final boolean mustBeSuccesfull)
187 | throws Exception {
188 |
189 | final String [] userpass = getUserPass();
190 |
191 | client = getJestClient(getServerUri(),userpass[0],userpass[1]);
192 |
193 |
194 | final JestResult res = client.execute(new Index.Builder(loadFile(file)).index(index).type(type).id(id).refresh(true)
195 | .setHeader(headers).build());
196 |
197 | log.debug("Index operation result: " + res.getJsonString());
198 | if (mustBeSuccesfull) {
199 | Assert.assertTrue(res.isSucceeded());
200 | } else {
201 | Assert.assertTrue(!res.isSucceeded());
202 | }
203 |
204 | return res;
205 | }
206 |
207 |
208 |
209 | protected JestResult executeSearch(final String file,
210 | final boolean mustBeSuccesfull) throws Exception {
211 |
212 | final String [] userpass = getUserPass();
213 |
214 | client = getJestClient(getServerUri(),userpass[0],userpass[1]);
215 |
216 |
217 | final JestResult res = client.execute(new Search.Builder(loadFile(file)).refresh(true).setHeader(headers)
218 | .build());
219 |
220 | log.debug("Search operation result: " + res.getJsonString());
221 | if (mustBeSuccesfull) {
222 | Assert.assertTrue(res.isSucceeded());
223 | } else {
224 | Assert.assertTrue(!res.isSucceeded());
225 | }
226 | return res;
227 | }
228 |
229 | protected JestResult executeGet(final String index, final String id,
230 | final boolean mustBeSuccesfull) throws Exception {
231 |
232 | final String [] userpass = getUserPass();
233 |
234 | client = getJestClient(getServerUri(),userpass[0],userpass[1]);
235 |
236 |
237 | final JestResult res = client.execute(new Get.Builder(index, id).refresh(true).setHeader(headers)
238 | .build());
239 |
240 | log.debug("Search operation result: " + res.getJsonString());
241 | if (mustBeSuccesfull) {
242 | Assert.assertTrue(res.isSucceeded());
243 | } else {
244 | Assert.assertTrue(!res.isSucceeded());
245 | }
246 | return res;
247 | }
248 |
249 | protected String [] getUserPass()
250 | {
251 | return new String[]{null,null};
252 | }
253 |
254 | /*private JestHttpClient getJestClient(String serverUri) throws Exception
255 | {
256 | return getJestClient(serverUri, null, null);
257 | }*/
258 |
259 |
260 | private JestHttpClient getJestClient(String serverUri, final String username,
261 | final String password) throws Exception {// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
262 | final HttpClientConfig clientConfig1 = new HttpClientConfig.Builder(serverUri)
263 | .multiThreaded(true).build();
264 |
265 | // Construct a new Jest client according to configuration via factory
266 | final JestClientFactory factory1 = new JestClientFactory();
267 |
268 | factory1.setHttpClientConfig(clientConfig1);
269 |
270 | final JestHttpClient c = (JestHttpClient) factory1.getObject();
271 |
272 | final HttpClientBuilder hcb = HttpClients.custom();
273 |
274 | if (serverUri.startsWith("https")) {
275 |
276 | log.info("Configure Jest with SSL");
277 |
278 | final KeyStore myTrustStore = KeyStore.getInstance("PKCS12");
279 | myTrustStore
280 | .load(new FileInputStream(
281 | SecurityUtil
282 | .getAbsoluteFilePathFromClassPath("localhost_tc.p12")),
283 | "changeit".toCharArray());
284 |
285 | final KeyStore keyStore = KeyStore.getInstance("PKCS12");
286 | keyStore.load(
287 | new FileInputStream(
288 | SecurityUtil
289 | .getAbsoluteFilePathFromClassPath("hnelsonclient.p12")),
290 | "changeit".toCharArray());
291 |
292 | final SSLContext sslContext = SSLContexts.custom().useTLS()
293 | .loadKeyMaterial(keyStore, "changeit".toCharArray())
294 | .loadTrustMaterial(myTrustStore)
295 |
296 | .build();
297 |
298 | final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
299 | sslContext);
300 |
301 | hcb.setSSLSocketFactory(sslsf);
302 |
303 | }
304 |
305 | if (username != null) {
306 |
307 | final GSSContext context = initGSS(new URL(serverUri), "spnego-client", username,password);
308 | final byte[] data = context.initSecContext(new byte[0], 0, 0);
309 |
310 | final List dh = new ArrayList();
311 | dh.add(new BasicHeader("Authorization","Negotiate "
312 | + org.apache.tomcat.util.codec.binary.Base64
313 | .encodeBase64String(data)));
314 |
315 | hcb.setDefaultHeaders(dh);
316 |
317 |
318 |
319 | }
320 |
321 | c.setHttpClient(hcb.build());
322 |
323 |
324 |
325 | return c;
326 |
327 | }
328 |
329 |
330 |
331 | private static CallbackHandler getUsernamePasswordHandler(
332 | final String username, final String password) {
333 |
334 | final CallbackHandler handler = new CallbackHandler() {
335 | @Override
336 | public void handle(final Callback[] callback) {
337 | for (int i = 0; i < callback.length; i++) {
338 | if (callback[i] instanceof NameCallback) {
339 | final NameCallback nameCallback = (NameCallback) callback[i];
340 | nameCallback.setName(username);
341 | } else if (callback[i] instanceof PasswordCallback) {
342 | final PasswordCallback passCallback = (PasswordCallback) callback[i];
343 | passCallback.setPassword(password.toCharArray());
344 | } else {
345 | System.out
346 | .println("Unsupported Callback i=" + i
347 | + "; class="
348 | + callback[i].getClass().getName());
349 | }
350 | }
351 | }
352 | };
353 |
354 | return handler;
355 | }
356 |
357 | private GSSContext initGSS(final URL url, String loginentry, String user, String password) throws Exception {
358 | final GSSManager MANAGER = GSSManager.getInstance();
359 |
360 | final LoginContext loginContext = new LoginContext(loginentry,
361 | getUsernamePasswordHandler(user,password));
362 | loginContext.login();
363 | final Subject subject = loginContext.getSubject();
364 |
365 | final PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
366 | @Override
367 | public GSSCredential run() throws GSSException {
368 | return MANAGER.createCredential(null,
369 | GSSCredential.DEFAULT_LIFETIME,
370 | new Oid("1.3.6.1.5.5.2"), GSSCredential.INITIATE_ONLY);
371 | }
372 | };
373 |
374 | final GSSCredential clientcreds = Subject.doAs(subject, action);
375 |
376 | final GSSContext context = MANAGER.createContext(MANAGER.createName(
377 | "HTTP@" + url.getHost(), GSSName.NT_HOSTBASED_SERVICE, new Oid(
378 | "1.3.6.1.5.5.2")), new Oid("1.3.6.1.5.5.2"),
379 | clientcreds, GSSContext.DEFAULT_LIFETIME);
380 |
381 | context.requestMutualAuth(true);
382 | context.requestConf(true);
383 | context.requestInteg(true);
384 | context.requestReplayDet(true);
385 | context.requestSequenceDet(true);
386 | context.requestCredDeleg(false);
387 |
388 | return context;
389 |
390 | /*byte[] data = context.initSecContext(new byte[0], 0, 0);
391 |
392 |
393 |
394 |
395 | final URLConnection uc = url.openConnection();
396 | uc.setRequestProperty(
397 | "Authorization",
398 | "Negotiate "
399 | + org.apache.tomcat.util.codec.binary.Base64
400 | .encodeBase64String(data));
401 | uc.connect();
402 | data = org.apache.tomcat.util.codec.binary.Base64.decodeBase64(uc
403 | .getHeaderField("WWW-Authenticate").split(" ")[1]);
404 |
405 | data = context.initSecContext(data, 0, data.length);
406 | if (!context.isEstablished()) {
407 | throw new Exception("context not established");
408 | }*/
409 |
410 | }
411 |
412 |
413 | }
414 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/SpnegoAdTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import java.net.URL;
4 | import java.util.Hashtable;
5 | import java.util.Properties;
6 |
7 | import javax.naming.Context;
8 | import javax.naming.NamingException;
9 | import javax.naming.directory.Attribute;
10 | import javax.naming.directory.Attributes;
11 | import javax.naming.directory.BasicAttribute;
12 | import javax.naming.directory.BasicAttributes;
13 | import javax.naming.directory.DirContext;
14 | import javax.naming.directory.InitialDirContext;
15 | import javax.naming.directory.ModificationItem;
16 | import javax.naming.ldap.InitialLdapContext;
17 | import javax.naming.ldap.LdapContext;
18 | import javax.security.auth.kerberos.KerberosPrincipal;
19 |
20 | import net.sourceforge.spnego.SpnegoHttpURLConnection;
21 |
22 | import org.apache.commons.io.IOUtils;
23 | import org.apache.directory.api.ldap.model.constants.SchemaConstants;
24 | import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
25 | import org.apache.directory.api.ldap.model.exception.LdapException;
26 | import org.apache.directory.api.ldap.model.message.ModifyRequest;
27 | import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
28 | import org.apache.directory.api.ldap.model.name.Dn;
29 | import org.apache.directory.server.annotations.CreateKdcServer;
30 | import org.apache.directory.server.annotations.CreateLdapServer;
31 | import org.apache.directory.server.annotations.CreateTransport;
32 | import org.apache.directory.server.annotations.SaslMechanism;
33 | import org.apache.directory.server.constants.ServerDNConstants;
34 | import org.apache.directory.server.core.annotations.ContextEntry;
35 | import org.apache.directory.server.core.annotations.CreateDS;
36 | import org.apache.directory.server.core.annotations.CreateIndex;
37 | import org.apache.directory.server.core.annotations.CreatePartition;
38 | import org.apache.directory.server.core.api.CoreSession;
39 | import org.apache.directory.server.core.api.DirectoryService;
40 | import org.apache.directory.server.core.integ.FrameworkRunner;
41 | import org.apache.directory.server.core.jndi.CoreContextFactory;
42 | import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
43 | import org.apache.directory.server.kerberos.kdc.KdcServer;
44 | import org.apache.directory.server.ldap.LdapServer;
45 | import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
46 | import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
47 | import org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler;
48 | import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
49 | import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
50 | import org.elasticsearch.plugins.security.util.SecurityUtil;
51 | import org.junit.Assert;
52 | import org.junit.Before;
53 | import org.junit.Test;
54 | import org.junit.runner.RunWith;
55 |
56 | @RunWith(FrameworkRunner.class)
57 | @CreateDS(name = "SaslGssapiBindITest-class", partitions = { @CreatePartition(name = "example", suffix = "dc=example,dc=com", contextEntry = @ContextEntry(entryLdif = "dn: dc=example,dc=com\n"
58 | + "dc: example\n" + "objectClass: top\n" + "objectClass: domain\n\n"), indexes = {
59 | @CreateIndex(attribute = "objectClass"),
60 | @CreateIndex(attribute = "dc"), @CreateIndex(attribute = "ou") }) }, additionalInterceptors = { KeyDerivationInterceptor.class })
61 | @CreateLdapServer(allowAnonymousAccess=true, transports = { @CreateTransport(protocol = "LDAP", port = 6389) }, saslHost = "localhost", saslPrincipal = "ldap/localhost@EXAMPLE.COM", saslMechanisms = {
62 | @SaslMechanism(name = SupportedSaslMechanisms.PLAIN, implClass = PlainMechanismHandler.class),
63 | @SaslMechanism(name = SupportedSaslMechanisms.CRAM_MD5, implClass = CramMd5MechanismHandler.class),
64 | @SaslMechanism(name = SupportedSaslMechanisms.DIGEST_MD5, implClass = DigestMd5MechanismHandler.class),
65 | @SaslMechanism(name = SupportedSaslMechanisms.GSSAPI, implClass = GssapiMechanismHandler.class),
66 | @SaslMechanism(name = SupportedSaslMechanisms.NTLM, implClass = NtlmMechanismHandler.class),
67 | @SaslMechanism(name = SupportedSaslMechanisms.GSS_SPNEGO, implClass = NtlmMechanismHandler.class) })
68 | @CreateKdcServer(transports = {
69 | @CreateTransport(protocol = "UDP", port = 6088, address = "localhost"),
70 | @CreateTransport(protocol = "TCP", port = 6088, address = "localhost") })
71 | public class SpnegoAdTests extends SpnegoTests {
72 |
73 | /*public static CallbackHandler getUsernamePasswordHandler(
74 | final String username, final String password) {
75 |
76 | final CallbackHandler handler = new CallbackHandler() {
77 | @Override
78 | public void handle(final Callback[] callback) {
79 | for (int i = 0; i < callback.length; i++) {
80 | if (callback[i] instanceof NameCallback) {
81 | final NameCallback nameCallback = (NameCallback) callback[i];
82 | nameCallback.setName(username);
83 | } else if (callback[i] instanceof PasswordCallback) {
84 | final PasswordCallback passCallback = (PasswordCallback) callback[i];
85 | passCallback.setPassword(password.toCharArray());
86 | } else {
87 | System.out
88 | .println("Unsupported Callback i=" + i
89 | + "; class="
90 | + callback[i].getClass().getName());
91 | }
92 | }
93 | }
94 | };
95 |
96 | return handler;
97 | }
98 |
99 | protected void initGSS(final URL url) throws Exception {
100 | final GSSManager MANAGER = GSSManager.getInstance();
101 |
102 | final LoginContext loginContext = new LoginContext("spnego-client",
103 | getUsernamePasswordHandler("hnelson", "secret"));
104 | loginContext.login();
105 | final Subject subject = loginContext.getSubject();
106 |
107 | final PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
108 | @Override
109 | public GSSCredential run() throws GSSException {
110 | return MANAGER.createCredential(null,
111 | GSSCredential.DEFAULT_LIFETIME,
112 | new Oid("1.3.6.1.5.5.2"), GSSCredential.INITIATE_ONLY);
113 | }
114 | };
115 |
116 | final GSSCredential clientcreds = Subject.doAs(subject, action);
117 |
118 | final GSSContext context = MANAGER.createContext(MANAGER.createName(
119 | "HTTP@" + url.getHost(), GSSName.NT_HOSTBASED_SERVICE, new Oid(
120 | "1.3.6.1.5.5.2")), new Oid("1.3.6.1.5.5.2"),
121 | clientcreds, GSSContext.DEFAULT_LIFETIME);
122 |
123 | context.requestMutualAuth(true);
124 | context.requestConf(true);
125 | context.requestInteg(true);
126 | context.requestReplayDet(true);
127 | context.requestSequenceDet(true);
128 | context.requestCredDeleg(false);
129 | byte[] data = context.initSecContext(new byte[0], 0, 0);
130 |
131 | final URLConnection uc = url.openConnection();
132 | uc.setRequestProperty("Authorization",
133 | "Negotiate " + org.apache.tomcat.util.codec.binary.Base64.encodeBase64String(data));
134 | uc.connect();
135 | data = org.apache.tomcat.util.codec.binary.Base64
136 | .decodeBase64(uc.getHeaderField("WWW-Authenticate").split(" ")[1]);
137 |
138 | data = context.initSecContext(data, 0, data.length);
139 | if (!context.isEstablished()) {
140 | throw new Exception("context not established");
141 | }
142 |
143 | }
144 |
145 | @Test
146 | public void getHeaderTest() throws Exception {
147 | final URL url = new URL("http://localhost:8080");
148 |
149 | SecurityUtil.setSystemPropertyToAbsoluteFilePathFromClassPath(
150 | "java.security.auth.login.config", "login.conf");
151 | this.initGSS(url);
152 |
153 | }*/
154 |
155 | // public static final String AUTHN_HEADER = "WWW-Authenticate";
156 | // public static final String AUTHZ_HEADER = "Authorization";
157 |
158 | private DirContext ctx;
159 |
160 | /** the context root for the schema */
161 | protected LdapContext schemaRoot;
162 |
163 | /** the context root for the system partition */
164 | protected LdapContext sysRoot;
165 |
166 | /** the context root for the rootDSE */
167 | protected CoreSession rootDse;
168 |
169 | /** The used DirectoryService instance */
170 | public static DirectoryService service;
171 |
172 | /** The used LdapServer instance */
173 | public static LdapServer ldapServer;
174 |
175 | /** The used KdcServer instance */
176 | public static KdcServer kdcServer;
177 |
178 | public static DirectoryService getService() {
179 | return service;
180 | }
181 |
182 | public static void setService(final DirectoryService service) {
183 | SpnegoAdTests.service = service;
184 | }
185 |
186 | public static LdapServer getLdapServer() {
187 | return ldapServer;
188 | }
189 |
190 | public static void setLdapServer(final LdapServer ldapServer) {
191 | SpnegoAdTests.ldapServer = ldapServer;
192 | }
193 |
194 | public static KdcServer getKdcServer() {
195 | return kdcServer;
196 | }
197 |
198 | public static void setKdcServer(final KdcServer kdcServer) {
199 | SpnegoAdTests.kdcServer = kdcServer;
200 | }
201 |
202 | @Override
203 | protected Properties getProperties() {
204 | final Properties props = new Properties();
205 | props.putAll(super.getProperties());
206 | props.setProperty("security.kerberos.mode", "spnegoad");
207 | props.setProperty("security.authorization.ldap.isactivedirectory", "false");
208 | props.setProperty("security.authorization.ldap.ldapurls", "ldap://localhost:6389");
209 |
210 | props.setProperty("security.authorization.ldap.connectionname", "uid=admin,ou=system");
211 | props.setProperty("security.authorization.ldap.connectionpassword", "secret");
212 | props.setProperty("security.authorization.ldap.usersearch", "uid={0}");
213 | props.setProperty("security.authorization.ldap.userbase", "ou=users,dc=example,dc=com");
214 | props.setProperty("security.authorization.ldap.rolebase", "ou=groups,dc=example,dc=com");
215 |
216 |
217 | props.setProperty("security.kerberos.login.conf.path", SecurityUtil.getAbsoluteFilePathFromClassPath("login.conf").getAbsolutePath());
218 | props.setProperty("security.kerberos.krb5.conf.path", SecurityUtil.getAbsoluteFilePathFromClassPath("krb5.conf").getAbsolutePath());
219 |
220 | //props.setProperty("security.module.actionpathfilter.enabled", "false");
221 | //props.setProperty("security.module.dls.enabled", "false");
222 |
223 | return props;
224 | }
225 |
226 |
227 |
228 | public SpnegoAdTests() {
229 | super();
230 |
231 |
232 | }
233 |
234 |
235 | @Override
236 | protected String [] getUserPass()
237 | {
238 | return new String[]{"hnelson", "secret"};
239 | }
240 |
241 | @Test
242 | public void spneghc() throws Exception {
243 |
244 | kdcServer.getConfig().setPaEncTimestampRequired(false);
245 |
246 | executeIndex("dls_default_test_allowall.json",
247 | "securityconfiguration", "dlspermissions", "default", true);
248 |
249 | executeIndex("dls_default_test_allowall.json",
250 | "securityconfiguration", "dlspermissions", "default", true);
251 |
252 | }
253 |
254 | @Test
255 | public void donothing() throws Exception {
256 |
257 | }
258 |
259 |
260 | @Test
261 | public void queryGETUrlTest() throws Exception {
262 |
263 | if(isSSL()) {
264 | return;
265 | }
266 |
267 | executeIndex("dls_default_test_allowall.json",
268 | "securityconfiguration", "dlspermissions", "default", true);
269 |
270 | executeIndex("dls_test_normal.json", "securityconfiguration",
271 | "dlspermissions", "dlspermissions", true);
272 |
273 | executeIndex("test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
274 | executeIndex("dummy_content.json", "twitter",
275 | "tweet", "1", true);
276 |
277 |
278 |
279 | final net.sourceforge.spnego.SpnegoHttpURLConnection hcon = new SpnegoHttpURLConnection(
280 | "spnego-client", "hnelson@EXAMPLE.COM", "secret");
281 |
282 | hcon.requestCredDeleg(true);
283 |
284 |
285 | hcon.connect(new URL(getServerUri() + "/_search"));
286 | //hcon.connect(new URL(getServerUri() + "/%5Fsearch"));
287 |
288 | Assert.assertTrue(hcon.getResponseCode() == 200);
289 |
290 | log.debug(IOUtils.toString(hcon.getInputStream()));
291 |
292 |
293 |
294 |
295 |
296 | }
297 |
298 |
299 |
300 | public static String fixServicePrincipalName(String servicePrincipalName,
301 | final Dn serviceEntryDn, final LdapServer ldapServer)
302 | throws LdapException {
303 | final KerberosPrincipal servicePrincipal = new KerberosPrincipal(
304 | servicePrincipalName, KerberosPrincipal.KRB_NT_SRV_HST);
305 | servicePrincipalName = servicePrincipal.getName();
306 |
307 | ldapServer.setSaslPrincipal(servicePrincipalName);
308 |
309 | if (serviceEntryDn != null) {
310 | final ModifyRequest modifyRequest = new ModifyRequestImpl();
311 | modifyRequest.setName(serviceEntryDn);
312 | modifyRequest.replace("userPassword", "randall");
313 | modifyRequest.replace("krb5PrincipalName", servicePrincipalName);
314 | ldapServer.getDirectoryService().getAdminSession()
315 | .modify(modifyRequest);
316 | }
317 |
318 | return servicePrincipalName;
319 | }
320 |
321 | /**
322 | * Set up a partition for EXAMPLE.COM and add user and service principals to
323 | * test authentication with.
324 | */
325 | @Override
326 | @Before
327 | public void setUp() throws Exception {
328 | super.setUp();
329 |
330 | getKdcServer().getConfig().setPrimaryRealm("EXAMPLE.COM");
331 |
332 | final String servicePrincipalName = fixServicePrincipalName(
333 | "ldap/localhost@EXAMPLE.COM", null, getLdapServer());
334 |
335 | // System.out.println("servicePrincipalName "+servicePrincipalName);
336 |
337 | Attributes attrs;
338 |
339 | this.setContexts("uid=admin,ou=system", "secret");
340 |
341 | // -------------------------------------------------------------------
342 | // Enable the krb5kdc schema
343 | // -------------------------------------------------------------------
344 |
345 | // check if krb5kdc is disabled
346 | final Attributes krb5kdcAttrs = schemaRoot
347 | .getAttributes("cn=Krb5kdc");
348 | boolean isKrb5KdcDisabled = false;
349 |
350 | if (krb5kdcAttrs.get("m-disabled") != null) {
351 | isKrb5KdcDisabled = ((String) krb5kdcAttrs.get("m-disabled").get())
352 | .equalsIgnoreCase("TRUE");
353 | }
354 |
355 | // if krb5kdc is disabled then enable it
356 | if (isKrb5KdcDisabled) {
357 | final Attribute disabled = new BasicAttribute("m-disabled");
358 | final ModificationItem[] mods = new ModificationItem[] { new ModificationItem(
359 | DirContext.REMOVE_ATTRIBUTE, disabled) };
360 | schemaRoot.modifyAttributes("cn=Krb5kdc", mods);
361 | }
362 |
363 | // Get a context, create the ou=users subcontext, then create the 3
364 | // principals.
365 | final Hashtable env = new Hashtable();
366 | env.put(DirectoryService.JNDI_KEY, getService());
367 | env.put(Context.INITIAL_CONTEXT_FACTORY,
368 | "org.apache.directory.server.core.jndi.CoreContextFactory");
369 | env.put(Context.PROVIDER_URL, "dc=example,dc=com");
370 | env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
371 | env.put(Context.SECURITY_CREDENTIALS, "secret");
372 | env.put(Context.SECURITY_AUTHENTICATION, "simple");
373 |
374 | ctx = new InitialDirContext(env);
375 |
376 | attrs = getOrgUnitAttributes("users");
377 | final DirContext users = ctx.createSubcontext("ou=users", attrs);
378 |
379 | attrs = getPrincipalAttributes("Nelson", "Horatio Nelson",
380 | "hnelson", "secret", "hnelson@EXAMPLE.COM");
381 | users.createSubcontext("uid=hnelson", attrs);
382 |
383 | attrs = getPrincipalAttributes("hNelson", "Horatio hNelson",
384 | "nelsonh", "secret", "nelsonh@EXAMPLE.COM");
385 | users.createSubcontext("uid=nelsonh", attrs);
386 |
387 | attrs = getPrincipalAttributes("Einstein", "Albert Einstein",
388 | "aeinstein", "aeinstein", "aeinstein@EXAMPLE.COM");
389 | users.createSubcontext("uid=aeinstein", attrs);
390 |
391 | attrs = getPrincipalAttributes("Service", "KDC Service", "krbtgt",
392 | "secret", "krbtgt/EXAMPLE.COM@EXAMPLE.COM");
393 | users.createSubcontext("uid=krbtgt", attrs);
394 |
395 | attrs = getPrincipalAttributes("Service", "LDAP Service", "ldap",
396 | "randall", servicePrincipalName);
397 | users.createSubcontext("uid=ldap", attrs);
398 |
399 | attrs = getPrincipalAttributes("Service", "HTTP Service", "http",
400 | "httppwd", "HTTP/localhost@EXAMPLE.COM");
401 | users.createSubcontext("uid=http", attrs);
402 |
403 | /*
404 | * dn: cn=itpeople,ou=groups,dc=example,dc=com objectclass: groupofnames
405 | * cn: itpeople description: IT security group member: cn=William
406 | * Smith,ou=people,dc=example,dc=com
407 | */
408 |
409 | attrs = getOrgUnitAttributes("groups");
410 | final DirContext groups = ctx.createSubcontext("ou=groups", attrs);
411 |
412 | attrs = getGroupAttributes(
413 | "uid=hnelson,ou=users,dc=example,dc=com", "dummy ldap role",
414 | "dummy_ldap");
415 | groups.createSubcontext("cn=dummy_ldap", attrs);
416 |
417 | attrs = getGroupAttributes(
418 | "uid=nelsonh,ou=users,dc=example,dc=com", "dummy ssl ldap role",
419 | "dummy_sslldap");
420 | groups.createSubcontext("cn=dummy_sslldap", attrs);
421 | }
422 |
423 | /**
424 | * Convenience method for creating principals.
425 | *
426 | * @param cn
427 | * the commonName of the person
428 | * @param principal
429 | * the kerberos principal name for the person
430 | * @param sn
431 | * the surName of the person
432 | * @param uid
433 | * the unique identifier for the person
434 | * @param userPassword
435 | * the credentials of the person
436 | * @return the attributes of the person principal
437 | */
438 | protected Attributes getPrincipalAttributes(final String sn,
439 | final String cn, final String uid, final String userPassword,
440 | final String principal) {
441 | final Attributes attrs = new BasicAttributes(true);
442 | final Attribute ocls = new BasicAttribute("objectClass");
443 | ocls.add("top");
444 | ocls.add("person"); // sn $ cn
445 | ocls.add("inetOrgPerson"); // uid
446 | ocls.add("krb5principal");
447 | ocls.add("krb5kdcentry");
448 | attrs.put(ocls);
449 | attrs.put("cn", cn);
450 | attrs.put("sn", sn);
451 | attrs.put("uid", uid);
452 | attrs.put("userPassword", userPassword);
453 | attrs.put("krb5PrincipalName", principal);
454 | attrs.put("krb5KeyVersionNumber", "0");
455 |
456 | return attrs;
457 | }
458 |
459 | protected Attributes getGroupAttributes(final String member,
460 | final String description, final String cn) {
461 | /*
462 | * dn: cn=itpeople,ou=groups,dc=example,dc=com objectclass: groupofnames
463 | * cn: itpeople description: IT security group member: cn=William
464 | * Smith,ou=people,dc=example,dc=com
465 | */
466 |
467 | final Attributes attrs = new BasicAttributes(true);
468 | final Attribute ocls = new BasicAttribute("objectClass");
469 | ocls.add("groupofnames");
470 | attrs.put(ocls);
471 | attrs.put("cn", cn);
472 | attrs.put("description", description);
473 | attrs.put("member", member);
474 |
475 | return attrs;
476 | }
477 |
478 | /**
479 | * Convenience method for creating an organizational unit.
480 | *
481 | * @param ou
482 | * the ou of the organizationalUnit
483 | * @return the attributes of the organizationalUnit
484 | */
485 | protected Attributes getOrgUnitAttributes(final String ou) {
486 | final Attributes attrs = new BasicAttributes(true);
487 | final Attribute ocls = new BasicAttribute("objectClass");
488 | ocls.add("top");
489 | ocls.add("organizationalUnit");
490 | attrs.put(ocls);
491 | attrs.put("ou", ou);
492 |
493 | return attrs;
494 | }
495 |
496 | protected void setContexts(final String user, final String passwd)
497 | throws Exception {
498 | final Hashtable env = new Hashtable();
499 | env.put(DirectoryService.JNDI_KEY, getService());
500 | env.put(Context.SECURITY_PRINCIPAL, user);
501 | env.put(Context.SECURITY_CREDENTIALS, passwd);
502 | env.put(Context.SECURITY_AUTHENTICATION, "simple");
503 | env.put(Context.INITIAL_CONTEXT_FACTORY,
504 | CoreContextFactory.class.getName());
505 | this.setContexts(env);
506 | }
507 |
508 | /**
509 | * Sets the contexts of this class taking into account the extras and
510 | * overrides properties.
511 | *
512 | * @param env
513 | * an environment to use while setting up the system root.
514 | * @throws NamingException
515 | * if there is a failure of any kind
516 | */
517 | protected void setContexts(final Hashtable env)
518 | throws Exception {
519 | final Hashtable envFinal = new Hashtable(
520 | env);
521 | envFinal.put(Context.PROVIDER_URL, ServerDNConstants.SYSTEM_DN);
522 | sysRoot = new InitialLdapContext(envFinal, null);
523 |
524 | envFinal.put(Context.PROVIDER_URL, "");
525 | rootDse = getService().getAdminSession();
526 |
527 | envFinal.put(Context.PROVIDER_URL, SchemaConstants.OU_SCHEMA);
528 | schemaRoot = new InitialLdapContext(envFinal, null);
529 | }
530 | /*
531 | private class CallbackHandlerBean implements CallbackHandler {
532 | private final String name;
533 | private final String password;
534 |
535 |
536 | public CallbackHandlerBean(final String name, final String password) {
537 | this.name = name;
538 | this.password = password;
539 | }
540 |
541 | @Override
542 | public void handle(final Callback[] callbacks)
543 | throws UnsupportedCallbackException, IOException {
544 | for (int ii = 0; ii < callbacks.length; ii++) {
545 | final Callback callBack = callbacks[ii];
546 |
547 | // Handles username callback.
548 | if (callBack instanceof NameCallback) {
549 | final NameCallback nameCallback = (NameCallback) callBack;
550 | nameCallback.setName(this.name);
551 | // Handles password callback.
552 | } else if (callBack instanceof PasswordCallback) {
553 | final PasswordCallback passwordCallback = (PasswordCallback) callBack;
554 | passwordCallback.setPassword(this.password.toCharArray());
555 | } else {
556 | throw new UnsupportedCallbackException(callBack,
557 | I18n.err(I18n.ERR_617));
558 | }
559 | }
560 | }
561 | }*/
562 | }
563 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/SpnegoAdTestsAlternateLdapUrl.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import java.net.URL;
4 | import java.util.Hashtable;
5 | import java.util.Properties;
6 |
7 | import javax.naming.Context;
8 | import javax.naming.NamingException;
9 | import javax.naming.directory.Attribute;
10 | import javax.naming.directory.Attributes;
11 | import javax.naming.directory.BasicAttribute;
12 | import javax.naming.directory.BasicAttributes;
13 | import javax.naming.directory.DirContext;
14 | import javax.naming.directory.InitialDirContext;
15 | import javax.naming.directory.ModificationItem;
16 | import javax.naming.ldap.InitialLdapContext;
17 | import javax.naming.ldap.LdapContext;
18 | import javax.security.auth.kerberos.KerberosPrincipal;
19 |
20 | import net.sourceforge.spnego.SpnegoHttpURLConnection;
21 |
22 | import org.apache.commons.io.IOUtils;
23 | import org.apache.directory.api.ldap.model.constants.SchemaConstants;
24 | import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
25 | import org.apache.directory.api.ldap.model.exception.LdapException;
26 | import org.apache.directory.api.ldap.model.message.ModifyRequest;
27 | import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
28 | import org.apache.directory.api.ldap.model.name.Dn;
29 | import org.apache.directory.server.annotations.CreateKdcServer;
30 | import org.apache.directory.server.annotations.CreateLdapServer;
31 | import org.apache.directory.server.annotations.CreateTransport;
32 | import org.apache.directory.server.annotations.SaslMechanism;
33 | import org.apache.directory.server.constants.ServerDNConstants;
34 | import org.apache.directory.server.core.annotations.ContextEntry;
35 | import org.apache.directory.server.core.annotations.CreateDS;
36 | import org.apache.directory.server.core.annotations.CreateIndex;
37 | import org.apache.directory.server.core.annotations.CreatePartition;
38 | import org.apache.directory.server.core.api.CoreSession;
39 | import org.apache.directory.server.core.api.DirectoryService;
40 | import org.apache.directory.server.core.integ.FrameworkRunner;
41 | import org.apache.directory.server.core.jndi.CoreContextFactory;
42 | import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
43 | import org.apache.directory.server.kerberos.kdc.KdcServer;
44 | import org.apache.directory.server.ldap.LdapServer;
45 | import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
46 | import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
47 | import org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler;
48 | import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
49 | import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
50 | import org.elasticsearch.plugins.security.util.SecurityUtil;
51 | import org.junit.Assert;
52 | import org.junit.Before;
53 | import org.junit.Test;
54 | import org.junit.runner.RunWith;
55 |
56 | @RunWith(FrameworkRunner.class)
57 | @CreateDS(name = "SaslGssapiBindITest-class", partitions = { @CreatePartition(name = "example", suffix = "dc=example,dc=com", contextEntry = @ContextEntry(entryLdif = "dn: dc=example,dc=com\n"
58 | + "dc: example\n" + "objectClass: top\n" + "objectClass: domain\n\n"), indexes = {
59 | @CreateIndex(attribute = "objectClass"),
60 | @CreateIndex(attribute = "dc"), @CreateIndex(attribute = "ou") }) }, additionalInterceptors = { KeyDerivationInterceptor.class })
61 | @CreateLdapServer(allowAnonymousAccess=true, transports = { @CreateTransport(protocol = "LDAP", port = 6389) }, saslHost = "localhost", saslPrincipal = "ldap/localhost@EXAMPLE.COM", saslMechanisms = {
62 | @SaslMechanism(name = SupportedSaslMechanisms.PLAIN, implClass = PlainMechanismHandler.class),
63 | @SaslMechanism(name = SupportedSaslMechanisms.CRAM_MD5, implClass = CramMd5MechanismHandler.class),
64 | @SaslMechanism(name = SupportedSaslMechanisms.DIGEST_MD5, implClass = DigestMd5MechanismHandler.class),
65 | @SaslMechanism(name = SupportedSaslMechanisms.GSSAPI, implClass = GssapiMechanismHandler.class),
66 | @SaslMechanism(name = SupportedSaslMechanisms.NTLM, implClass = NtlmMechanismHandler.class),
67 | @SaslMechanism(name = SupportedSaslMechanisms.GSS_SPNEGO, implClass = NtlmMechanismHandler.class) })
68 | @CreateKdcServer(transports = {
69 | @CreateTransport(protocol = "UDP", port = 6088, address = "localhost"),
70 | @CreateTransport(protocol = "TCP", port = 6088, address = "localhost") })
71 | public class SpnegoAdTestsAlternateLdapUrl extends SpnegoAdTests {
72 |
73 |
74 | @Override
75 | protected Properties getProperties() {
76 | final Properties props = new Properties();
77 | props.putAll(super.getProperties());
78 | props.setProperty("security.kerberos.mode", "spnegoad");
79 | props.setProperty("security.authorization.ldap.isactivedirectory", "false");
80 | props.setProperty("security.authorization.ldap.ldapurls", "ldap://dummy-non-existent:1234, ldap://localhost:6389");
81 |
82 | props.setProperty("security.authorization.ldap.connectionname", "uid=admin,ou=system");
83 | props.setProperty("security.authorization.ldap.connectionpassword", "secret");
84 | props.setProperty("security.authorization.ldap.usersearch", "uid={0}");
85 | props.setProperty("security.authorization.ldap.userbase", "ou=users,dc=example,dc=com");
86 | props.setProperty("security.authorization.ldap.rolebase", "ou=groups,dc=example,dc=com");
87 |
88 |
89 | props.setProperty("security.kerberos.login.conf.path", SecurityUtil.getAbsoluteFilePathFromClassPath("login.conf").getAbsolutePath());
90 | props.setProperty("security.kerberos.krb5.conf.path", SecurityUtil.getAbsoluteFilePathFromClassPath("krb5.conf").getAbsolutePath());
91 |
92 | //props.setProperty("security.module.actionpathfilter.enabled", "false");
93 | //props.setProperty("security.module.dls.enabled", "false");
94 |
95 | return props;
96 | }
97 |
98 |
99 |
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/SpnegoTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import io.searchbox.client.JestResult;
4 |
5 | import java.util.Properties;
6 |
7 | import org.junit.Assert;
8 | import org.junit.Test;
9 |
10 | public abstract class SpnegoTests extends AbstractUnitTest {
11 |
12 | @Override
13 | protected Properties getProperties() {
14 |
15 | final Properties props = new Properties();
16 | props.putAll(super.getProperties());
17 | props.setProperty("security.http.xforwardedfor.header",
18 | "X-Forwarded-For");
19 | props.setProperty("security.http.xforwardedfor.trustedproxies",
20 | "123.123.123.123, 111.222.111.222");
21 | return props;
22 | }
23 |
24 |
25 |
26 | // ---
27 |
28 | @Test
29 | public void common_normalTest() throws Exception {
30 |
31 | executeIndex("ur_test_normal.json","securityconfiguration","actionpathfilter","actionpathfilter",true);
32 | executeIndex("dummy_content.json","twitter","tweet","1",true);
33 |
34 | }
35 |
36 | @Test
37 | public void common_dupTest() throws Exception {
38 |
39 |
40 | executeIndex("ur_test_duplicate.json","securityconfiguration","actionpathfilter","actionpathfilter",true);
41 | executeIndex("dummy_content.json","twitter","tweet","1",false);
42 |
43 | }
44 |
45 | // --
46 |
47 | @Test
48 | public void singleHeaderTest() throws Exception {
49 |
50 | executeIndex("test_normal.json","securityconfiguration","actionpathfilter","actionpathfilter",true);
51 | executeIndex("dls_default_test_allowall.json","securityconfiguration","dlspermissions","default",true);
52 | executeIndex("dls_test_normal.json","securityconfiguration","dlspermissions","dlspermissions",true);
53 |
54 | headers.put("X-Forwarded-For", "3.1.55.2");
55 | executeSearch("non_field_query.json",true);
56 |
57 | }
58 |
59 | @Test
60 | public void badProxiesTest() throws Exception {
61 |
62 | executeIndex("dls_default_test_allowall.json",
63 | "securityconfiguration", "dlspermissions", "default", true);
64 |
65 | executeIndex("dls_test_normal.json", "securityconfiguration",
66 | "dlspermissions", "dlspermissions", true);
67 |
68 | executeIndex("test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
69 |
70 | headers.put("X-Forwarded-For",
71 | "3.1.55.2, 123.12.123.123, 111.222.111.222");
72 | executeSearch("non_field_query.json", false);
73 |
74 |
75 | }
76 |
77 | @Test
78 | public void goodProxiesTest() throws Exception {
79 |
80 | executeIndex("dls_default_test_allowall.json",
81 | "securityconfiguration", "dlspermissions", "default", true);
82 |
83 | executeIndex("dls_test_normal.json", "securityconfiguration",
84 | "dlspermissions", "dlspermissions", true);
85 |
86 | executeIndex("test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
87 |
88 |
89 | headers.put("X-Forwarded-For",
90 | "3.1.55.2, 123.123.123.123, 111.222.111.222");
91 | executeSearch("non_field_query.json", true);
92 |
93 |
94 |
95 | }
96 |
97 | @Test
98 | public void goodProxiesTestSingle() throws Exception {
99 |
100 | executeIndex("dls_default_test_allowall.json",
101 | "securityconfiguration", "dlspermissions", "default", true);
102 |
103 | executeIndex("dls_test_normal.json", "securityconfiguration",
104 | "dlspermissions", "dlspermissions", true);
105 |
106 | executeIndex("test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
107 |
108 |
109 | headers.put("X-Forwarded-For",
110 | "3.1.55.2, 123.123.123.123");
111 | executeSearch("non_field_query.json", true);
112 |
113 |
114 | }
115 |
116 |
117 | // --
118 | @Test
119 | public void normalTest2() throws Exception {
120 |
121 | executeIndex("dls_default_test_denyall.json",
122 | "securityconfiguration", "dlspermissions", "default", true);
123 | executeIndex("ur_test_normal.json", "securityconfiguration",
124 | "actionpathfilter", "actionpathfilter", true);
125 | executeIndex("dls_test_normal.json", "securityconfiguration",
126 | "dlspermissions", "dlspermissions", true);
127 | executeIndex("dls_dummy_content.json", "twitter", "tweet", "1",
128 | true);
129 | executeIndex("dls_dummy_content_without_dls.json", "twitter",
130 | "tweet", "2", true);
131 | executeSearch("dls_field_query.json", true);
132 |
133 | }
134 |
135 | @Test
136 | public void normalTest22() throws Exception {
137 |
138 |
139 | executeIndex("ur_test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
140 |
141 | executeIndex("dls_test_normal.json", "securityconfiguration",
142 | "dlspermissions", "dlspermissions", true);
143 |
144 |
145 | executeIndex("dls_dummy_content_without_dls.json", "twitter",
146 | "tweet", "1", true);
147 |
148 | executeSearch("dls_field_query.json", true);
149 |
150 | }
151 |
152 | // --
153 | // dls
154 |
155 | @Test
156 | public void normalTest() throws Exception {
157 |
158 | executeIndex("ur_test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
159 |
160 | executeIndex("dls_test_normal.json", "securityconfiguration",
161 | "dlspermissions", "dlspermissions", true);
162 |
163 | executeIndex("dls_dummy_content.json", "twitter",
164 | "tweet", "1", true);
165 |
166 | executeIndex("dls_dummy_content_updt.json", "twitter",
167 | "tweet", "1", true);
168 |
169 |
170 | executeSearch("dls_field_query.json", true);
171 |
172 | }
173 |
174 | @Test
175 | public void facetTest() throws Exception {
176 |
177 | executeIndex("ur_test_all.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
178 |
179 | executeIndex("dls_test_normal.json", "securityconfiguration",
180 | "dlspermissions", "dlspermissions", true);
181 |
182 | executeIndex("dls_dummy_content.json", "twitter",
183 | "tweet", "1", true);
184 |
185 | JestResult res = executeSearch("test_facet_search.json", true);
186 |
187 | Assert.assertTrue(res.getJsonString().contains("facets"));
188 | Assert.assertTrue(res.getJsonString().contains("term"));
189 |
190 |
191 | }
192 |
193 | /*@Test
194 | public void facetTestStrict() throws Exception {
195 |
196 | this.esSetup..put("security.strict", "true");
197 |
198 | executeIndex("ur_test_all.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
199 |
200 | executeIndex("dls_test_normal.json", "securityconfiguration",
201 | "dlspermissions", "dlspermissions", true);
202 |
203 | executeIndex("dls_dummy_content.json", "twitter",
204 | "tweet", "1", true);
205 |
206 | JestResult res = executeSearch("test_facet_search.json", true);
207 |
208 | Assert.assertTrue(!res.getJsonString().contains("facets"));
209 | Assert.assertTrue(!res.getJsonString().contains("term"));
210 |
211 |
212 | }*/
213 |
214 | @Test
215 | public void normalTest23() throws Exception {
216 |
217 | executeIndex("ur_test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
218 |
219 |
220 | executeIndex("dls_test_normal.json", "securityconfiguration",
221 | "dlspermissions", "dlspermissions", true);
222 |
223 | executeIndex("dls_dummy_content.json", "twitter",
224 | "tweet", "1", true);
225 |
226 | executeSearch("dls_field_query.json", true);
227 |
228 | }
229 |
230 | // --
231 |
232 | @Test
233 | public void denyAllTest() throws Exception {
234 |
235 | executeIndex("test_denyall.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
236 |
237 |
238 | executeIndex("dummy_content.json", "twitter",
239 | "tweet", "1", false);
240 |
241 |
242 |
243 | }
244 |
245 | @Test
246 | public void allowTest() throws Exception {
247 |
248 |
249 | executeIndex("test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
250 |
251 |
252 |
253 | executeIndex("dummy_content.json", "twitter",
254 | "tweet", "1", true);
255 |
256 |
257 | }
258 |
259 |
260 | @Test
261 | public void issueDls1() throws Exception {
262 |
263 | executeIndex("ur_test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
264 |
265 |
266 | executeIndex("issues/dls1/default.json", "securityconfiguration","dlspermissions","default", true);
267 |
268 | executeIndex("issues/dls1/rules.json", "securityconfiguration",
269 | "dlspermissions", "dlspermissions", true);
270 |
271 | executeIndex("dls_dummy_content.json", "twitter",
272 | "tweet", "1", true);
273 |
274 | executeSearch("dls_field_query.json", true);
275 |
276 | }
277 |
278 |
279 | @Test
280 | public void issueDls2() throws Exception {
281 |
282 | executeIndex("ur_test_normal.json", "securityconfiguration", "actionpathfilter", "actionpathfilter",true );
283 |
284 |
285 | executeIndex("issues/dls2/default.json", "securityconfiguration","dlspermissions","default", true);
286 |
287 | executeIndex("issues/dls2/rules.json", "securityconfiguration",
288 | "dlspermissions", "dlspermissions", true);
289 |
290 | executeIndex("issues/dls2/data.json", "logstash-2014.04.03",
291 | "log", "onelog", true);
292 |
293 | JestResult res = executeGet("logstash-2014.04.03","onelog", true);
294 | Assert.assertEquals(loadFile("issues/dls2/expected.json"), res.getJsonString());
295 |
296 | }
297 |
298 |
299 |
300 | }
301 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/SpnegoWaffleTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import java.util.Properties;
4 |
5 | import org.junit.Before;
6 |
7 | public class SpnegoWaffleTests extends SpnegoTests {
8 |
9 | @Override
10 | protected Properties getProperties() {
11 | final Properties props = new Properties();
12 | props.putAll(super.getProperties());
13 | props.setProperty("security.kerberos.mode", "waffle");
14 | props.setProperty("security.waffle.testmode", "true");
15 | return props;
16 | }
17 |
18 |
19 | @Override
20 | @Before
21 | public void setUp() throws Exception {
22 | super.setUp();
23 | headers.put("Authorization", "foo bar");
24 | }
25 |
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/SslSpnegoAdTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security;
2 |
3 | import java.util.Properties;
4 |
5 | import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
6 | import org.apache.directory.server.annotations.CreateKdcServer;
7 | import org.apache.directory.server.annotations.CreateLdapServer;
8 | import org.apache.directory.server.annotations.CreateTransport;
9 | import org.apache.directory.server.annotations.SaslMechanism;
10 | import org.apache.directory.server.core.annotations.ContextEntry;
11 | import org.apache.directory.server.core.annotations.CreateDS;
12 | import org.apache.directory.server.core.annotations.CreateIndex;
13 | import org.apache.directory.server.core.annotations.CreatePartition;
14 | import org.apache.directory.server.core.integ.FrameworkRunner;
15 | import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
16 | import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
17 | import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
18 | import org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler;
19 | import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
20 | import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
21 | import org.elasticsearch.plugins.security.util.SecurityUtil;
22 | import org.junit.Before;
23 | import org.junit.runner.RunWith;
24 | @RunWith(FrameworkRunner.class)
25 | @CreateDS(name = "SaslGssapiBindITest-class", partitions = { @CreatePartition(name = "example", suffix = "dc=example,dc=com", contextEntry = @ContextEntry(entryLdif = "dn: dc=example,dc=com\n"
26 | + "dc: example\n" + "objectClass: top\n" + "objectClass: domain\n\n"), indexes = {
27 | @CreateIndex(attribute = "objectClass"),
28 | @CreateIndex(attribute = "dc"), @CreateIndex(attribute = "ou") }) }, additionalInterceptors = { KeyDerivationInterceptor.class })
29 | @CreateLdapServer(allowAnonymousAccess=true, transports = { @CreateTransport(protocol = "LDAP", port = 6389) }, saslHost = "localhost", saslPrincipal = "ldap/localhost@EXAMPLE.COM", saslMechanisms = {
30 | @SaslMechanism(name = SupportedSaslMechanisms.PLAIN, implClass = PlainMechanismHandler.class),
31 | @SaslMechanism(name = SupportedSaslMechanisms.CRAM_MD5, implClass = CramMd5MechanismHandler.class),
32 | @SaslMechanism(name = SupportedSaslMechanisms.DIGEST_MD5, implClass = DigestMd5MechanismHandler.class),
33 | @SaslMechanism(name = SupportedSaslMechanisms.GSSAPI, implClass = GssapiMechanismHandler.class),
34 | @SaslMechanism(name = SupportedSaslMechanisms.NTLM, implClass = NtlmMechanismHandler.class),
35 | @SaslMechanism(name = SupportedSaslMechanisms.GSS_SPNEGO, implClass = NtlmMechanismHandler.class) })
36 | @CreateKdcServer(transports = {
37 | @CreateTransport(protocol = "UDP", port = 6088, address = "localhost"),
38 | @CreateTransport(protocol = "TCP", port = 6088, address = "localhost") })
39 | public class SslSpnegoAdTests extends SpnegoAdTests {
40 |
41 | @Override
42 | protected Properties getProperties() {
43 | final Properties props = new Properties();
44 | props.putAll(super.getProperties());
45 |
46 | props.setProperty("security.ssl.enabled", "true");
47 | props.setProperty("security.ssl.keystorefile", SecurityUtil.getAbsoluteFilePathFromClassPath("localhost_tc.p12").getAbsolutePath()); //"C:\\cygwin\\home\\salyh\\pki-simple\\v2\\certs\\localhost_tc.p12
48 | props.setProperty("security.ssl.keystoretype", "PKCS12");
49 |
50 | props.setProperty("security.ssl.clientauth.enabled", "true");
51 | props.setProperty("security.ssl.clientauth.truststorefile", SecurityUtil.getAbsoluteFilePathFromClassPath("truststore.jks").getAbsolutePath());
52 |
53 | props.setProperty("security.ssl.userattribute","CN");
54 | //props.setProperty("security.module.actionpathfilter.enabled", "false");
55 | //props.setProperty("security.module.dls.enabled", "false");
56 |
57 |
58 |
59 | return props;
60 | }
61 |
62 |
63 | @Override
64 | @Before
65 | public void setUp() throws Exception {
66 | super.setUp();
67 |
68 | }
69 |
70 | @Override
71 | protected boolean isSSL() {
72 | return true;
73 | }
74 |
75 | /*
76 | @Test
77 | public void testSSL() throws Exception
78 |
79 | {
80 |
81 | final String krbConfPath = URLDecoder.decode(this.getClass()
82 | .getClassLoader().getResource("krb5.conf").getFile(),
83 | "UTF-8");
84 |
85 | System.setProperty("java.security.krb5.conf", krbConfPath);
86 | System.setProperty("sun.security.krb5.debug", "true");
87 |
88 | SecurityUtil.setSystemPropertyToAbsoluteFilePathFromClassPath("java.security.auth.login.config", "login.conf");
89 |
90 | System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
91 |
92 | KeyStore myTrustStore = KeyStore.getInstance("PKCS12");
93 | myTrustStore.load(new FileInputStream(SecurityUtil.getAbsoluteFilePathFromClassPath("localhost_tc.p12")), "changeit".toCharArray());
94 |
95 | KeyStore keyStore = KeyStore.getInstance("PKCS12");
96 | keyStore.load(new FileInputStream(SecurityUtil.getAbsoluteFilePathFromClassPath("hnelsonclient.p12")), "changeit".toCharArray());
97 |
98 |
99 |
100 | SSLContext sslContext = SSLContexts.custom()
101 | .useTLS()
102 | .loadKeyMaterial(keyStore, "changeit".toCharArray())
103 | .loadTrustMaterial(myTrustStore)
104 |
105 | .build();
106 |
107 |
108 |
109 | SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
110 |
111 | CloseableHttpClient httpclient = HttpClients.custom()
112 |
113 | .setSSLSocketFactory(sslsf)
114 | .build();
115 |
116 |
117 | final ClientConfig clientConfig1 = new ClientConfig.Builder("https://localhost:8080/")
118 | .multiThreaded(true).build();
119 |
120 | // Construct a new Jest client according to configuration via factory
121 | JestClientFactory factory1 = new JestClientFactory();
122 |
123 | factory1.setClientConfig(clientConfig1);
124 |
125 | JestHttpClient c = (JestHttpClient) factory1.getObject();
126 | c.setHttpClient(httpclient);
127 |
128 | JestResult res = c.execute(new Index.Builder(this
129 | .loadFile("ur_test_normal.json"))
130 | .index("securityconfiguration").type("actionpathfilter")
131 | .id("actionpathfilter").refresh(true)
132 | .setHeader("Authorization", "foo bar").build());
133 |
134 |
135 | res = c.execute(new Search.Builder(this
136 | .loadFile("field_query.json")).refresh(true)
137 | .setHeader("Authorization", "foo bar").build());
138 |
139 | this.log.info(res.getJsonString());
140 | Assert.assertTrue(res.isSucceeded());
141 |
142 | }*/
143 | }
144 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/filter/AbstractPermTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.io.IOException;
4 | import java.io.StringWriter;
5 |
6 | import org.apache.commons.io.IOUtils;
7 | import org.elasticsearch.plugins.security.service.permission.UserRoleCallback;
8 | import org.junit.Rule;
9 | import org.junit.rules.TestName;
10 | import org.junit.rules.TestWatcher;
11 | import org.junit.runner.Description;
12 |
13 | public class AbstractPermTests {
14 |
15 | @Rule
16 | public TestName name = new TestName();
17 |
18 | @Rule
19 | public TestWatcher testWatcher = new TestWatcher() {
20 | @Override
21 | protected void starting(final Description description) {
22 | String methodName = description.getMethodName();
23 | String className = description.getClassName();
24 | className = className.substring(className.lastIndexOf('.') + 1);
25 | System.out.println("Starting JUnit-test: " + className + " " + methodName);
26 | }
27 | };
28 |
29 | protected String loadFile(final String file) throws IOException {
30 |
31 | final StringWriter sw = new StringWriter();
32 | IOUtils.copy(this.getClass().getResourceAsStream("/" + file), sw);
33 | return sw.toString();
34 |
35 | }
36 |
37 |
38 | static class TestCallback implements UserRoleCallback {
39 |
40 | private final String user;
41 | private final String role;
42 |
43 | protected TestCallback(final String user, final String role) {
44 | super();
45 | this.user = user;
46 | this.role = role;
47 | }
48 |
49 | @Override
50 | public String getRemoteuser() {
51 | // TODO Auto-generated method stub
52 | return user;
53 | }
54 |
55 | @Override
56 | public boolean isRemoteUserInRole(final String role) {
57 | // TODO Auto-generated method stub
58 | return role.equals(this.role);
59 | }
60 |
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/filter/DlsTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import java.net.InetAddress;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import junit.framework.Assert;
10 |
11 | import org.elasticsearch.plugins.security.filter.AbstractPermTests.TestCallback;
12 | import org.elasticsearch.plugins.security.service.permission.PermEvaluator;
13 | import org.junit.Test;
14 |
15 | public class DlsTests extends AbstractPermTests {
16 |
17 | @Test
18 | public void testNormal1() throws Exception {
19 |
20 | final List tokens = new ArrayList();
21 | tokens.add("default");
22 | tokens.add("everyone");
23 | final PermEvaluator> evaluator = new PermDlsEvaluator(
24 | loadFile("dls_test_normal.json"));
25 | assertTrue(evaluator.evaluatePerm(null, null,
26 | InetAddress.getByName("8.8.8.8"), null).equals(tokens));
27 |
28 | }
29 |
30 | @Test
31 | public void testNormal2() throws Exception {
32 |
33 | final List tokens = new ArrayList();
34 | tokens.add("guesttoken");
35 | final PermEvaluator> evaluator = new PermDlsEvaluator(
36 | loadFile("dls_test_normal.json"));
37 | assertTrue(evaluator.evaluatePerm(null, null,
38 | InetAddress.getByName("8.8.8.8"), new TestCallback("Guest", "guest")).equals(tokens));
39 |
40 | }
41 |
42 | @Test
43 | public void testEmptyArraysAllow() throws Exception {
44 |
45 | final List tokens = new ArrayList();
46 | tokens.add("guesttoken");
47 |
48 | final PermEvaluator> evaluator = new PermDlsEvaluator(
49 | loadFile("dls_allow_emptyarray.json"));
50 |
51 | org.junit.Assert.assertEquals(tokens, evaluator.evaluatePerm(null, null,
52 | InetAddress.getByName("8.8.8.8"), null));
53 |
54 |
55 | }
56 |
57 | @Test
58 | public void testEmptyArrays() throws Exception {
59 |
60 | final List tokens = new ArrayList();
61 |
62 | final PermEvaluator> evaluator = new PermDlsEvaluator(
63 | loadFile("dls_denyall_emptyarray.json"));
64 |
65 | org.junit.Assert.assertEquals(tokens, evaluator.evaluatePerm(null, null,
66 | InetAddress.getByName("8.8.8.8"), null));
67 |
68 |
69 | }
70 |
71 |
72 | @Test
73 | public void issueDls1() throws Exception {
74 |
75 | final List tokens = new ArrayList();
76 | final PermEvaluator> evaluator = new PermDlsEvaluator(
77 | loadFile("issues/dls1/rules.json"));
78 | assertTrue(evaluator.evaluatePerm(null, null,
79 | InetAddress.getByName("8.8.8.8"), null).equals(tokens));
80 |
81 | }
82 |
83 | @Test
84 | public void issueDls2() throws Exception {
85 |
86 | List tokens = new ArrayList();
87 | tokens.add("t_everyone");
88 |
89 | final List indices = new ArrayList();
90 | indices.add("testindex1");
91 |
92 |
93 | final PermEvaluator> evaluator = new PermDlsEvaluator(
94 | loadFile("issues/dls2/rules.json"));
95 | assertTrue(evaluator.evaluatePerm(indices, null,
96 | InetAddress.getByName("8.8.8.8"), null).equals(tokens));
97 |
98 | }
99 |
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/filter/SecurityPermTests.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.filter;
2 |
3 | import java.io.IOException;
4 | import java.io.StringWriter;
5 | import java.net.InetAddress;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import org.apache.commons.io.IOUtils;
10 | import org.elasticsearch.plugins.security.MalformedConfigurationException;
11 | import org.elasticsearch.plugins.security.service.permission.PermEvaluator;
12 | import org.elasticsearch.plugins.security.service.permission.UserRoleCallback;
13 | import org.junit.Rule;
14 | import org.junit.Test;
15 | import org.junit.rules.TestName;
16 | import org.junit.rules.TestWatcher;
17 | import org.junit.runner.Description;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | /**
22 | * Unit test for simple App.
23 | */
24 | public class SecurityPermTests extends AbstractPermTests{
25 |
26 | @Test(expected=IllegalArgumentException.class)
27 | public void testEmptyConfigException() {
28 |
29 | final List indices = new ArrayList();
30 | indices.add("testindex1");
31 | indices.add("testindex2");
32 | new PermLevelEvaluator(null);
33 | }
34 |
35 |
36 | @Test
37 | public void testDefault() throws Exception {
38 |
39 | final List indices = new ArrayList();
40 | indices.add("testindex1");
41 | indices.add("testindex2");
42 | final PermEvaluator> evaluator = new PermLevelEvaluator(
43 | loadFile("test_default.json"));
44 | assertTrue(evaluator.evaluatePerm(indices, null,
45 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.ALL);
46 | }
47 | @Test
48 | public void testNormalCases() throws Exception {
49 |
50 | final List indices = new ArrayList();
51 | indices.add("testindex1");
52 | indices.add("testindex2");
53 |
54 | final PermEvaluator> evaluator = new PermLevelEvaluator(
55 | loadFile("test_normal.json"));
56 | assertTrue(evaluator.evaluatePerm(indices, null,
57 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.ALL);
58 |
59 | assertTrue(evaluator.evaluatePerm(indices, null,
60 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.READWRITE);
61 | assertTrue(evaluator.evaluatePerm(indices, null,
62 | InetAddress.getByName("127.0.01"), null) == PermLevel.READONLY);
63 | assertTrue(evaluator.evaluatePerm(indices, null,
64 | InetAddress.getByName("1.2.3.4"), null) == PermLevel.NONE);
65 | }
66 | @Test
67 | public void testNormalCasesWithUserRoleTypes() throws Exception {
68 |
69 | final List indices = new ArrayList();
70 | indices.add("testindex1");
71 | indices.add("testindex2");
72 |
73 | final List types = new ArrayList();
74 | types.add("secrettype");
75 |
76 | final PermEvaluator> evaluator = new PermLevelEvaluator(
77 | loadFile("test_normal_withuserroletypes.json"));
78 | assertTrue(evaluator.evaluatePerm(indices, types, InetAddress
79 | .getByName("127.0.01"), new TestCallback("mister", "unknown")) == PermLevel.READONLY);
80 |
81 | assertTrue(evaluator.evaluatePerm(indices, types, InetAddress
82 | .getByName("127.0.01"), new TestCallback("kirk", "unknown")) == PermLevel.READWRITE);
83 |
84 | assertTrue(evaluator.evaluatePerm(indices, types, InetAddress
85 | .getByName("8.8.8.8"), new TestCallback("kirk", "unknown")) == PermLevel.ALL);
86 |
87 | }
88 | @Test
89 | public void testNormalIndicesCases() throws Exception {
90 |
91 | final List indices = new ArrayList();
92 | indices.add("testindex1");
93 |
94 | final PermEvaluator> evaluator = new PermLevelEvaluator(
95 | loadFile("test_normal_indices.json"));
96 | assertTrue(evaluator.evaluatePerm(indices, null,
97 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.ALL);
98 | assertTrue(evaluator.evaluatePerm(indices, null,
99 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.READWRITE);
100 | assertTrue(evaluator.evaluatePerm(indices, null,
101 | InetAddress.getByName("128.0.0.1"), null) == PermLevel.ALL);
102 | assertTrue(evaluator.evaluatePerm(indices, null,
103 | InetAddress.getByName("1.2.3.4"), null) == PermLevel.NONE);
104 | }
105 | @Test
106 | public void testWildcardIndicesCases() throws Exception {
107 |
108 | final List indices = new ArrayList();
109 | indices.add("testindex1");
110 |
111 | final PermEvaluator> evaluator = new PermLevelEvaluator(
112 | loadFile("test_wildcard_indices.json"));
113 |
114 | assertTrue(evaluator.evaluatePerm(indices, null,
115 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.ALL);
116 | assertTrue(evaluator.evaluatePerm(indices, null,
117 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.READWRITE);
118 | assertTrue(evaluator.evaluatePerm(indices, null,
119 | InetAddress.getByName("128.0.0.1"), null) == PermLevel.ALL);
120 | assertTrue(evaluator.evaluatePerm(indices, null,
121 | InetAddress.getByName("1.2.3.4"), null) == PermLevel.NONE);
122 | }
123 | @Test
124 | public void testWildcardMultipleIndicesCases() throws Exception {
125 |
126 | final List indices = new ArrayList();
127 | indices.add("testindex1");
128 | indices.add("testindex3");
129 |
130 | final PermEvaluator> evaluator = new PermLevelEvaluator(
131 | loadFile("test_multiple_wildcard_indices.json"));
132 |
133 | assertTrue(evaluator.evaluatePerm(indices, null,
134 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.NONE);
135 | assertTrue(evaluator.evaluatePerm(indices, null,
136 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.READWRITE);
137 | assertTrue(evaluator.evaluatePerm(indices, null,
138 | InetAddress.getByName("127.1.0.1"), null) == PermLevel.NONE);
139 |
140 | assertTrue(evaluator.evaluatePerm(indices, null,
141 | InetAddress.getByName("1.2.3.4"), null) == PermLevel.ALL);
142 | }
143 | @Test
144 | public void testWildcardIndicesCases2() throws Exception {
145 |
146 | final List indices = new ArrayList();
147 | indices.add("testindex");
148 | indices.add("xtestindexy");
149 |
150 | final PermEvaluator> evaluator = new PermLevelEvaluator(
151 | loadFile("test_wildcard_indices2.json"));
152 |
153 | assertTrue(evaluator.evaluatePerm(indices, null,
154 | InetAddress.getByName("127.0.0.1"), null) == PermLevel.READWRITE);
155 |
156 | }
157 | @Test
158 | public void testWildcardIndicesCases22() throws Exception {
159 |
160 | final List indices = new ArrayList();
161 | indices.add("testindex-1020");
162 | indices.add("testindex-9");
163 |
164 | final PermEvaluator> evaluator = new PermLevelEvaluator(
165 | loadFile("test_wildcard_indices2.json"));
166 |
167 | assertTrue(evaluator.evaluatePerm(indices, null,
168 | InetAddress.getByName("127.0.0.1"), null) == PermLevel.ALL);
169 |
170 | }
171 | @Test
172 | public void testWildcardCases() throws Exception {
173 |
174 | final List indices = new ArrayList();
175 | indices.add("testindex1");
176 | indices.add("testindex2");
177 |
178 | final PermEvaluator> evaluator = new PermLevelEvaluator(
179 | loadFile("test_wildcard.json"));
180 | assertTrue(evaluator.evaluatePerm(indices, null,
181 | InetAddress.getByName("8.9.8.9"), null) == PermLevel.ALL);
182 | assertTrue(evaluator.evaluatePerm(indices, null,
183 | InetAddress.getByName("8.9.12.8"), null) == PermLevel.READWRITE);
184 | assertTrue(evaluator.evaluatePerm(indices, null,
185 | InetAddress.getByName("127.4.0.1"), null) == PermLevel.READONLY);
186 | assertTrue(evaluator.evaluatePerm(indices, null,
187 | InetAddress.getByName("103.2.3.4"), null) == PermLevel.NONE);
188 | }
189 | @Test
190 | public void testNormalCasesFQHN() throws Exception {
191 |
192 | final List indices = new ArrayList();
193 | indices.add("testindex1");
194 | indices.add("testindex2");
195 |
196 | final PermEvaluator> evaluator = new PermLevelEvaluator(
197 | loadFile("test_normal_fqn.json"));
198 | assertTrue(evaluator.evaluatePerm(indices, null,
199 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.NONE);
200 | assertTrue(evaluator.evaluatePerm(indices, null,
201 | InetAddress.getByName("google-public-dns-a.google.com"), null) == PermLevel.NONE);
202 |
203 | }
204 | @Test
205 | public void testWildcardCasesFQHN() throws Exception {
206 |
207 | final List indices = new ArrayList();
208 | indices.add("testindex1");
209 | indices.add("testindex2");
210 |
211 | final PermEvaluator> evaluator = new PermLevelEvaluator(
212 | loadFile("test_wildcard_fqn.json"));
213 | assertTrue(evaluator.evaluatePerm(indices, null,
214 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.NONE);
215 | assertTrue(evaluator.evaluatePerm(indices, null,
216 | InetAddress.getByName("google-public-dns-a.google.com"), null) == PermLevel.NONE);
217 |
218 | }
219 | @Test
220 | public void testBadFormat() throws Exception {
221 |
222 | final List indices = new ArrayList();
223 | indices.add("testindex1");
224 | indices.add("testindex2");
225 |
226 | final PermEvaluator> evaluator = new PermLevelEvaluator(
227 | loadFile("test_bad_format.json"));
228 |
229 | try {
230 | assertTrue(evaluator.evaluatePerm(indices, null,
231 | InetAddress.getByName("127.0.0.1"), null) == PermLevel.NONE);
232 | fail();
233 | } catch (final MalformedConfigurationException e) {
234 |
235 | }
236 |
237 | }
238 | @Test
239 | public void testNoDefault() throws Exception {
240 |
241 | final List indices = new ArrayList();
242 | indices.add("testindex1");
243 | indices.add("testindex2");
244 |
245 | final PermEvaluator> evaluator = new PermLevelEvaluator(
246 | loadFile("test_no_default.json"));
247 | try {
248 | assertTrue(evaluator.evaluatePerm(indices, null,
249 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.ALL);
250 | fail();
251 | } catch (final MalformedConfigurationException e) {
252 |
253 | }
254 |
255 | }
256 | @Test
257 | public void testMalformedStructure() throws Exception {
258 |
259 | final List indices = new ArrayList();
260 | indices.add("testindex1");
261 | indices.add("testindex2");
262 |
263 | final PermEvaluator> evaluator = new PermLevelEvaluator(
264 | loadFile("test_malformed_structure.json"));
265 | try {
266 | assertTrue(evaluator.evaluatePerm(indices, null,
267 | InetAddress.getByName("8.8.8.9"), null) == PermLevel.ALL);
268 | fail();
269 | } catch (final MalformedConfigurationException e) {
270 |
271 | }
272 |
273 | }
274 |
275 | @Test
276 | public void testEmptyArrays() throws Exception {
277 |
278 | final PermEvaluator> evaluator = new PermLevelEvaluator(
279 | loadFile("test_denyall_emptyarray.json"));
280 |
281 | assertTrue(evaluator.evaluatePerm(null, null,
282 | InetAddress.getByName("8.8.8.8"), null) == PermLevel.NONE);
283 |
284 |
285 | }
286 |
287 | }
288 |
--------------------------------------------------------------------------------
/src/test/java/org/elasticsearch/plugins/security/waffle/TestProvider.java:
--------------------------------------------------------------------------------
1 | package org.elasticsearch.plugins.security.waffle;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 |
8 | import waffle.mock.MockWindowsAuthProvider;
9 | import waffle.servlet.spi.SecurityFilterProvider;
10 | import waffle.windows.auth.IWindowsAuthProvider;
11 | import waffle.windows.auth.IWindowsIdentity;
12 |
13 | public class TestProvider implements SecurityFilterProvider {
14 |
15 | private MockWindowsAuthProvider _auth = null;
16 |
17 | public TestProvider(final IWindowsAuthProvider auth) {
18 | _auth = new MockWindowsAuthProvider();
19 | // System.out.println("ctor()");
20 |
21 | }
22 |
23 | @Override
24 | public void sendUnauthorized(final HttpServletResponse response) {
25 | // TODO Auto-generated method stub
26 | // System.out.println("sendUnauthorized()");
27 | }
28 |
29 | @Override
30 | public boolean isPrincipalException(final HttpServletRequest request) {
31 | // System.out.println("isPrincipalException()");
32 | return false;
33 | }
34 |
35 | @Override
36 | public IWindowsIdentity doFilter(final HttpServletRequest request,
37 | final HttpServletResponse response) throws IOException {
38 | // TODO Auto-generated method stub
39 | // System.out.println("auth guest");
40 | return _auth.logonUser("Guest", "");
41 | }
42 |
43 | @Override
44 | public boolean isSecurityPackageSupported(final String securityPackage) {
45 | // System.out.println("support " + securityPackage);
46 | return true;
47 | }
48 |
49 | @Override
50 | public void initParameter(final String parameterName,
51 | final String parameterValue) {
52 | // TODO Auto-generated method stub
53 | // System.out.println("init " + parameterName + "=" + parameterValue);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/resources/dls_allow_emptyarray.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts":[],
5 | "indices":[],
6 | "types":[],
7 | "users":[],
8 | "roles":[],
9 | "dlstoken" : ["guesttoken"]
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_default_test_allowall.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions":
3 | {
4 | "*" :
5 | {
6 | "read" :["*"],
7 | "update" : ["*"],
8 | "delete" : ["*"]
9 | }
10 |
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_default_test_denyall.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions":
3 | {
4 | "*" :
5 | {
6 | "read" :[],
7 | "update" : [],
8 | "delete" : []
9 | }
10 |
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_denyall_emptyarray.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts":[],
5 | "indices":[],
6 | "types":[],
7 | "users":[],
8 | "roles":[],
9 | "dlstoken" : []
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_dummy_content.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions":
3 | {
4 | "*" :
5 | {
6 | "read" :[],
7 | "update" : [],
8 | "delete" : []
9 | },
10 |
11 | "message" :
12 | {
13 | "read" :[ "guesttoken" ],
14 | "update" : [ "guesttoken","admin"],
15 | "delete" : []
16 | },
17 |
18 | "payload.level_12.*" :
19 | {
20 | "read" :[ "guesttoken" ],
21 | "update" : [ "guesttoken","admin"],
22 | "delete" : []
23 | }
24 | },
25 |
26 | "twitteruser" : "olomo1",
27 | "post_date" : "2009-11-15T14:12:12",
28 | "message" : "playing with Elastic Search",
29 | "payload" : {
30 | "level_1":"hello_level_1",
31 | "level_12":
32 | {
33 | "level_2":[
34 |
35 | {
36 | "min":"a",
37 | "max":"b"
38 | },
39 | {
40 | "min":"c",
41 | "max":"d"
42 | }
43 |
44 |
45 | ]
46 | }
47 |
48 | }
49 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_dummy_content_updt.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions":
3 | {
4 | "*" :
5 | {
6 | "read" :[],
7 | "update" : [],
8 | "delete" : []
9 | },
10 |
11 | "message" :
12 | {
13 | "read" :[ "guesttoken" ],
14 | "update" : [ "guesttoken","admin"],
15 | "delete" : []
16 | },
17 |
18 | "payload.level_12.*" :
19 | {
20 | "read" :[ "guesttoken" ],
21 | "update" : [ "guesttoken","admin"],
22 | "delete" : []
23 | }
24 | },
25 |
26 | "twitteruser" : "olomo1",
27 | "post_date" : "2013-11-15T14:12:12",
28 | "message" : "playing with updated docs",
29 | "payload" : {
30 | "level_1":"hello_level_1",
31 | "level_12":
32 | {
33 | "level_2":[
34 |
35 | {
36 | "min":"a",
37 | "max":"b"
38 | },
39 | {
40 | "min":"c",
41 | "max":"d"
42 | }
43 |
44 |
45 | ]
46 | }
47 |
48 | }
49 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_dummy_content_without_dls.json:
--------------------------------------------------------------------------------
1 | {
2 | "user" : "misterx",
3 | "post_date" : "2008-11-15T14:12:12",
4 | "message" : "some stuff here"
5 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_field_query.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "query" : {
4 | "term" : { "twitteruser" : "olomo1" }
5 | }
6 | }
--------------------------------------------------------------------------------
/src/test/resources/dls_test_normal.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "dlstoken" : [ "default,everyone" ]
5 | },
6 | {
7 | "users" : [ "Guest" ],
8 | "dlstoken" : [ "guesttoken" ]
9 | },
10 | {
11 | "roles" : [ "admin","marketing" ],
12 | "dlstoken" : [ "abstracttoken1,tokenx" ]
13 | }
14 | ,
15 | {
16 | "roles" : [ "admin","marketing" ],
17 | "types" : ["type1","type2"],
18 | "dlstoken" : [ "abstracttoken1,tokenx" ]
19 | }
20 | ]
21 | }
--------------------------------------------------------------------------------
/src/test/resources/dummy_content.json:
--------------------------------------------------------------------------------
1 | {
2 | "user" : "saly",
3 | "post_date" : "2009-11-15T14:12:12",
4 | "message" : "playing with Elastic Search"
5 | }
--------------------------------------------------------------------------------
/src/test/resources/hnelsonclient.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/salyh/elasticsearch-security-plugin/1d7f63db18c9f10171a8afe50dce0bd5f56000dc/src/test/resources/hnelsonclient.p12
--------------------------------------------------------------------------------
/src/test/resources/issues/dls1/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions": {
3 | "*": {
4 | "read": [ "*" ],
5 | "update": [],
6 | "delete": []
7 | },
8 | "message": {
9 | "read": [ "t_admin" ],
10 | "update": [ "t_admin" ],
11 | "delete": [ "t_admin" ]
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/test/resources/issues/dls1/rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" : [ "*" ],
6 | "types" : [ "*" ],
7 | "dlstoken" : [ ]
8 | },
9 | {
10 | "hosts" : [ "*" ],
11 | "indices" : [ "logstash.*" ],
12 | "types" : [ "*" ],
13 | "dlstoken" : [ "t_admin" ]
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/issues/dls2/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "loglevel": "INFO",
3 | "message": "INFO - this is an INFO message",
4 | "@timestamp": "2014-04-03T07:57:39.180Z"
5 | }
--------------------------------------------------------------------------------
/src/test/resources/issues/dls2/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "dlspermissions": {
3 | "*": {
4 | "read": [],
5 | "update": [],
6 | "delete": []
7 | },
8 | "loglevel": {
9 | "read": [ "t_everyone" ],
10 | "update": [ "t_admin" ],
11 | "delete": [ "t_admin" ]
12 | },
13 | "@timestamp": {
14 | "read": [ "t_everyone" ],
15 | "update": [ "t_admin" ],
16 | "delete": [ "t_admin" ]
17 | },
18 | "message": {
19 | "read": [ "t_admin" ],
20 | "update": [ "t_admin" ],
21 | "delete": [ "t_admin" ]
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/resources/issues/dls2/expected.json:
--------------------------------------------------------------------------------
1 | {"_type":"log","_version":1,"_source":{"@timestamp":"2014-04-03T07:57:39.180Z","loglevel":"INFO"},"_id":"onelog","_index":"logstash-2014.04.03","found":true}
--------------------------------------------------------------------------------
/src/test/resources/issues/dls2/rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" : [ "*" ],
6 | "types" : [ "*" ],
7 | "dlstoken" : [ "t_everyone" ]
8 | },
9 | {
10 | "hosts" : [ "one-not-existing-host" ],
11 | "indices" : [ "*" ],
12 | "types" : [ "*" ],
13 | "dlstoken" : [ "t_admin" ]
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/resources/krb5.conf:
--------------------------------------------------------------------------------
1 | [libdefaults]
2 | default_realm = EXAMPLE.COM
3 | forwardable=true
4 | default_tkt_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
5 | default_tgs_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
6 |
7 | [realms]
8 | EXAMPLE.COM = {
9 | kdc = localhost:6088
10 | default_domain = EXAMPLE.COM
11 | }
12 |
13 | [domain_realm]
14 | .example.com = EXAMPLE.COM
15 | example.com = EXAMPLE.COM
16 |
17 | [login]
18 | krb4_convert = true
19 | krb4_get_tickets = false
--------------------------------------------------------------------------------
/src/test/resources/krb5_utest.keytab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/salyh/elasticsearch-security-plugin/1d7f63db18c9f10171a8afe50dce0bd5f56000dc/src/test/resources/krb5_utest.keytab
--------------------------------------------------------------------------------
/src/test/resources/localhost_tc.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/salyh/elasticsearch-security-plugin/1d7f63db18c9f10171a8afe50dce0bd5f56000dc/src/test/resources/localhost_tc.p12
--------------------------------------------------------------------------------
/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=WARN, out
2 |
3 | log4j.appender.out=org.apache.log4j.ConsoleAppender
4 | log4j.appender.out.layout=org.apache.log4j.PatternLayout
5 | log4j.appender.out.layout.conversionPattern=[%d{HH:mm:ss}][%-5p] %c - %m%n
6 |
7 | log4j.logger.org.apache.catalina.startup=ERROR
8 | log4j.logger.org.apache.catalina.loader.WebappClassLoader=FATAL
9 | log4j.logger.org.elasticsearch.plugins.security=ALL
10 | #log4j.logger.net.sf.michaelo=ALL
11 | #log4j.logger.waffle=INFO
12 |
13 |
14 | #log4j.logger.org.apache.http.wire=ALL
15 | #log4j.logger.org.apache.catalina.authenticator=ALL
16 | #log4j.logger.org.apache.catalina.realm=ALL
17 | #log4j.logger.org.apache.catalina.core.ContainerBase=ALL
18 | #log4j.logger.org.apache.directory=WARN
--------------------------------------------------------------------------------
/src/test/resources/login.conf:
--------------------------------------------------------------------------------
1 | spnego-client {
2 | com.sun.security.auth.module.Krb5LoginModule
3 | required
4 | refreshKrb5Config=true
5 | storeKey=true
6 | useTicketCache=false
7 | ;
8 | };
9 |
10 |
11 | com.sun.security.jgss.krb5.accept {
12 | com.sun.security.auth.module.Krb5LoginModule
13 | required
14 | refreshKrb5Config=true
15 | storeKey=true
16 | isInitiator=false
17 | principal="HTTP/localhost@EXAMPLE.COM"
18 | doNotPrompt=true
19 | useKeyTab=true
20 | keyTab="${project.build.testOutputDirectory}${path.delim}krb5_utest.keytab"
21 | ;
22 | };
23 |
--------------------------------------------------------------------------------
/src/test/resources/non_field_query.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "query" : {
4 | "term" : { "user" : "saly" }
5 | }
6 | }
--------------------------------------------------------------------------------
/src/test/resources/test_bad_format.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "host" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "garbage" : "ALL"
7 | },
8 | {
9 | "jean" : [ "192.0.*.*"],
10 | "luc" :[ "index1", "myindex" ],
11 | "picard" : "READWRITE"
12 | },
13 | {
14 | "james" : ["another*.*.comapny.de" ],
15 | "t" :[ "index3"],
16 | "kirk" : "ALL"
17 | }
18 | ]
19 | }
--------------------------------------------------------------------------------
/src/test/resources/test_default.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 | {
9 | "hosts" : [ "192.0.*.*"],
10 | "indices" :[ "index1", "myindex" ],
11 | "permission" : "READWRITE"
12 | },
13 | {
14 | "hosts" : ["another*.*.comapny.de" ],
15 | "indices" :[ "index3"],
16 | "permission" : "ALL"
17 | }
18 | ]
19 | }
--------------------------------------------------------------------------------
/src/test/resources/test_denyall.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "NONE"
7 | }
8 | ]
9 | }
--------------------------------------------------------------------------------
/src/test/resources/test_denyall_emptyarray.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts":[],
5 | "indices":[],
6 | "types":[],
7 | "users":[],
8 | "roles":[],
9 | "permission" : "NONE"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/src/test/resources/test_facet_search.json:
--------------------------------------------------------------------------------
1 | {
2 | "query" : { "query_string" : {"query" : "*"} },
3 | "facets" : {
4 | "tags" : { "terms" : {"field" : "twitteruser"} }
5 | }
6 | }
--------------------------------------------------------------------------------
/src/test/resources/test_malformed_structure.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 |
4 | {
5 | "hosts : [ "192.0.*.*"],
6 | "indices" : "index1", "myindex" ],
7 | "permission" : "READWRITE"
8 | ,
9 | {
10 | "hosts" : ["another*.*.comapny.de" ],
11 | "indices" :[ "index3"],
12 | "permission" : "ALL"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/src/test/resources/test_multiple_wildcard_indices.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "NONE"
7 | },
8 | {
9 | "hosts" : [ "1.2.3.4" ],
10 | "indices" :[ "testindex1","testindex3" ],
11 | "permission" : "ALL"
12 | },
13 | {
14 | "hosts" : [ "127.0.0.1" ],
15 | "indices" :[ "testindex2" ],
16 | "permission" : "READONLY"
17 | },
18 | {
19 | "hosts" : [ "8.8.8.8" ],
20 | "indices" :[ "*" ],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/resources/test_no_default.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 |
4 | {
5 | "hosts" : [ "192.0.*.*"],
6 | "indices" :[ "index1", "myindex" ],
7 | "permission" : "READWRITE"
8 | },
9 | {
10 | "hosts" : ["another*.*.comapny.de" ],
11 | "indices" :[ "index3"],
12 | "permission" : "ALL"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/src/test/resources/test_normal.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 | {
9 | "hosts" : [ "1.2.3.4" ],
10 | "indices" :[ "*" ],
11 | "permission" : "NONE"
12 | },
13 | {
14 | "hosts" : [ "127.0.0.1" ],
15 | "indices" :[ "testindex1","testindex2" ],
16 | "permission" : "READONLY"
17 | },
18 | {
19 | "hosts" : [ "8.8.8.8" ],
20 | "indices" :[ "testindex1","testindex2"],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/test/resources/test_normal_fqn.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 |
9 | {
10 | "hosts" : [ "google-public-dns-a.google.com" ],
11 | "indices" :[ "*"],
12 | "permission" : "NONE"
13 | }
14 | ]
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/test_normal_indices.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 | {
9 | "hosts" : [ "1.2.3.4" ],
10 | "indices" :[ "testindex1" ],
11 | "permission" : "NONE"
12 | },
13 | {
14 | "hosts" : [ "127.0.0.1" ],
15 | "indices" :[ "testindex2" ],
16 | "permission" : "READONLY"
17 | },
18 | {
19 | "hosts" : [ "8.8.8.8" ],
20 | "indices" :[ "testindex1" ],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/resources/test_normal_withuserroletypes.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "permission" : "READONLY"
5 | },
6 | {
7 |
8 | "roles" : ["batmanrole"],
9 | "indices" :["testindex1","testindex2" ],
10 | "types" : ["secrettype"],
11 | "permission" : "READWRITE"
12 | },
13 | {
14 |
15 | "roles" : ["batmanrole"],
16 | "indices" :["testindex3" ],
17 | "permission" : "NONE"
18 | },
19 | {
20 | "users" : ["robin"],
21 | "permission" : "ALL"
22 | },
23 | {
24 | "hosts" : ["8.8.8.*"],
25 | "permission" : "ALL"
26 | },
27 | {
28 |
29 | "hosts" : ["9.9.*.*"],
30 | "indices" :["testindex1","testindex2" ],
31 | "permission" : "NONE"
32 | },
33 | {
34 | "users" : ["kirk","spock"],
35 | "indices" :["testindex1","testindex2" ],
36 | "permission" : "READWRITE"
37 | }
38 | ]
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/src/test/resources/test_wildcard.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 | {
9 | "hosts" : [ "*.2.3.4" ],
10 | "indices" :[ "*" ],
11 | "permission" : "NONE"
12 | },
13 | {
14 | "hosts" : [ "127.*.0.1" ],
15 | "indices" :[ "testindex1","testindex2" ],
16 | "permission" : "READONLY"
17 | },
18 | {
19 | "hosts" : [ "8.*.*.8" ],
20 | "indices" :[ "testindex1","testindex2"],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/test/resources/test_wildcard_fqn.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 |
9 | {
10 | "hosts" : [ "*google.com" ],
11 | "indices" :[ "*"],
12 | "permission" : "NONE"
13 | }
14 | ]
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/test_wildcard_indices.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "hosts" : [ "*" ],
5 | "indices" :[ "*" ],
6 | "permission" : "ALL"
7 | },
8 | {
9 | "hosts" : [ "1.2.3.4" ],
10 | "indices" :[ "*" ],
11 | "permission" : "NONE"
12 | },
13 | {
14 | "hosts" : [ "127.0.0.1" ],
15 | "indices" :[ "testindex2" ],
16 | "permission" : "READONLY"
17 | },
18 | {
19 | "hosts" : [ "8.8.8.8" ],
20 | "indices" :[ "*" ],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/resources/test_wildcard_indices2.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 |
4 | {
5 |
6 | "permission" : "NONE"
7 | },
8 | {
9 | "hosts" : [ "127.0.0.1" ],
10 | "indices" :[ "testindex-*" ],
11 | "permission" : "ALL"
12 | },
13 | {
14 | "hosts" : [ "127.0.0.1" ],
15 | "indices" :[ "*testindex*" ],
16 | "permission" : "READWRITE"
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/resources/truststore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/salyh/elasticsearch-security-plugin/1d7f63db18c9f10171a8afe50dce0bd5f56000dc/src/test/resources/truststore.jks
--------------------------------------------------------------------------------
/src/test/resources/ur_test_all.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "permission" : "ALL"
5 | }
6 | ]
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/test/resources/ur_test_duplicate.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "permission" : "NONE"
5 | },
6 | {
7 | "hosts" : [ "1.2.3.4" ],
8 |
9 | "permission" : "NONE"
10 | },
11 | {
12 | "hosts" : [ "*" ],
13 | "users" : [ "Picard","Spock","Guest","Me" ],
14 | "roles" : [ "Commander","Guest","Role1" ],
15 | "indices" :[ "*" ],
16 | "permission" : "READWRITE"
17 | },
18 |
19 | {
20 | "hosts" : [ "8.8.8.8" ],
21 | "indices" :[ "testindex1","testindex2"],
22 | "permission" : "READWRITE"
23 | },
24 | {
25 | "hosts" : [ "*" ],
26 | "users" : [ "Spock","Guest","Me","Picard" ],
27 | "roles" : [ "Role1","Commander","Guest" ],
28 | "indices" :[ "*" ],
29 | "permission" : "READWRITE"
30 | }
31 | ]
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/test/resources/ur_test_normal.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "permission" : "NONE"
5 | },
6 | {
7 | "hosts" : [ "1.2.3.4" ],
8 |
9 | "permission" : "NONE"
10 | },
11 | {
12 | "hosts" : [ "*" ],
13 | "users" : [ "Picard","Spock","Guest","Me","hnelson","nelsonh" ],
14 | "roles" : [ "Commander","Guest","Role1","dummy_ldap","dummy_sslldap" ],
15 | "indices" :[ "*" ],
16 | "permission" : "READWRITE"
17 | },
18 | {
19 | "hosts" : [ "8.8.8.8" ],
20 | "indices" :[ "testindex1","testindex2"],
21 | "permission" : "READWRITE"
22 | }
23 | ]
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/travisscripts/travis-before-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | sudo sed -i 's/localhost.localdomain//' /etc/hosts
4 |
--------------------------------------------------------------------------------