blob: 1348fd34f35a8fa78e9864c14395e03db6534cc6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.solr.security;
import java.security.Principal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.hadoop.security.authentication.server.AuthenticationToken;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.Utils;
import org.apache.solr.handler.UpdateRequestHandler;
import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.security.AuthorizationContext.RequestType;
import org.junit.Test;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.apache.solr.common.util.Utils.makeMap;
import static org.junit.Assert.assertEquals;
public class InfraRuleBasedAuthorizationPluginTest {
private static final String PERMISSIONS = "{" +
" user-host : {" +
" 'infra-solr@EXAMPLE.COM': [hostname, hostname2]" +
" }," +
" user-role : {" +
" 'infra-solr@EXAMPLE.COM': [admin]," +
" 'logsearch@EXAMPLE.COM': [logsearch_role,dev]," +
" 'logfeeder@EXAMPLE.COM': [logsearch_role,dev]," +
" 'atlas@EXAMPLE.COM': [atlas_role, audit_role, dev]," +
" 'knox@EXAMPLE.COM': [audit_role,dev]," +
" 'hdfs@EXAMPLE.COM': [audit_role,dev]," +
" 'hbase@EXAMPLE.COM': [audit_role,dev]," +
" 'yarn@EXAMPLE.COM': [audit_role,dev]," +
" 'knox@EXAMPLE.COM': [audit_role,dev]," +
" 'kafka@EXAMPLE.COM': [audit_role,dev]," +
" 'kms@EXAMPLE.COM': [audit_role,dev]," +
" 'storm@EXAMPLE.COM': [audit_role,dev]," +
" 'rangeradmin@EXAMPLE.COM':[ranger_role, audit_role, dev]" +
" }," +
" permissions : [" +
" {name:'collection-admin-read'," +
" role:null}," +
" {name:collection-admin-edit ," +
" role:[logsearch_role, atlas_role, ranger_role, admin]}," +
" {name:mycoll_update," +
" collection:mycoll," +
" path:'/*'," +
" role:[logsearch_role,admin]" +
" }," +
" {name:mycoll2_update," +
" collection:mycoll2," +
" path:'/*'," +
" role:[ranger_role, audit_role, admin]" +
" }," +
"{name:read , role:dev }]}";
@Test
public void testPermissions() {
int STATUS_OK = 200;
int FORBIDDEN = 403;
int PROMPT_FOR_CREDENTIALS = 401;
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "POST",
"userPrincipal", "tim",
"collectionRequests", "mycoll",
"handler", new UpdateRequestHandler())
, FORBIDDEN);
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "POST",
"userPrincipal", "logsearch",
"collectionRequests", "mycoll",
"handler", new UpdateRequestHandler())
, STATUS_OK);
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "GET",
"userPrincipal", "rangeradmin",
"collectionRequests", "mycoll",
"handler", new UpdateRequestHandler())
, FORBIDDEN);
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "GET",
"userPrincipal", "rangeradmin",
"collectionRequests", "mycoll2",
"handler", new UpdateRequestHandler())
, STATUS_OK);
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "GET",
"userPrincipal", "logsearch",
"collectionRequests", "mycoll2",
"handler", new UpdateRequestHandler())
, FORBIDDEN);
checkRules(makeMap("resource", "/update/json/docs",
"httpMethod", "POST",
"userPrincipal", "kms",
"collectionRequests", "mycoll2",
"handler", new UpdateRequestHandler())
, STATUS_OK);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", "tim",
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "CREATE")))
, FORBIDDEN);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", null,
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "CREATE")))
, PROMPT_FOR_CREDENTIALS);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", "rangeradmin",
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "CREATE")))
, STATUS_OK);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", "kms",
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "CREATE")))
, FORBIDDEN);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", "kms",
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "LIST")))
, STATUS_OK);
checkRules(makeMap("resource", "/admin/collections",
"userPrincipal", "rangeradmin",
"requestType", RequestType.ADMIN,
"collectionRequests", null,
"handler" , new CollectionsHandler(),
"params", new MapSolrParams(singletonMap("action", "LIST")))
, STATUS_OK);
}
private void checkRules(Map<String, Object> values, int expected) {
checkRules(values,expected,(Map) Utils.fromJSONString(PERMISSIONS));
}
private void checkRules(Map<String, Object> values, int expected, Map<String ,Object> permissions) {
AuthorizationContext context = new MockAuthorizationContext(values);
InfraRuleBasedAuthorizationPlugin plugin = new InfraRuleBasedAuthorizationPlugin();
plugin.init(permissions);
AuthorizationResponse authResp = plugin.authorize(context);
assertEquals(expected, authResp.statusCode);
}
private static class MockAuthorizationContext extends AuthorizationContext {
private final Map<String,Object> values;
private MockAuthorizationContext(Map<String, Object> values) {
this.values = values;
}
@Override
public SolrParams getParams() {
SolrParams params = (SolrParams) values.get("params");
return params == null ? new MapSolrParams(new HashMap<String, String>()) : params;
}
@Override
public Principal getUserPrincipal() {
Object userPrincipal = values.get("userPrincipal");
return userPrincipal == null ? null :
new AuthenticationToken(String.valueOf(userPrincipal), String.format("%s%s", String.valueOf(userPrincipal), "/hostname@EXAMPLE.COM"), "kerberos");
}
@Override
public String getHttpHeader(String header) {
return null;
}
@Override
public Enumeration getHeaderNames() {
return null;
}
@Override
public String getRemoteAddr() {
return null;
}
@Override
public String getRemoteHost() {
return null;
}
@Override
public List<CollectionRequest> getCollectionRequests() {
Object collectionRequests = values.get("collectionRequests");
if (collectionRequests instanceof String) {
return singletonList(new CollectionRequest((String)collectionRequests));
}
return (List<CollectionRequest>) collectionRequests;
}
@Override
public RequestType getRequestType() {
return (RequestType) values.get("requestType");
}
@Override
public String getHttpMethod() {
return (String) values.get("httpMethod");
}
@Override
public String getResource() {
return (String) values.get("resource");
}
@Override
public Object getHandler() {
Object handler = values.get("handler");
return handler instanceof String ? (PermissionNameProvider) request -> PermissionNameProvider.Name.get((String) handler) : handler;
}
}
}