PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/solr/core/src/java/org/apache/solr/security/MultiAuthRuleBasedAuthorizationPlugin.java

https://github.com/apache/solr
Java | 164 lines | 113 code | 19 blank | 32 comment | 21 complexity | 01f2e8d5e5f1c79765c77c09aab4edd5 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.solr.security;
  18. import static org.apache.solr.security.MultiAuthPlugin.applyEditCommandToSchemePlugin;
  19. import java.security.Principal;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.HashSet;
  23. import java.util.LinkedHashMap;
  24. import java.util.List;
  25. import java.util.Locale;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import org.apache.lucene.util.ResourceLoader;
  29. import org.apache.solr.common.SolrException;
  30. import org.apache.solr.common.StringUtils;
  31. import org.apache.solr.common.util.CommandOperation;
  32. import org.apache.solr.core.CoreContainer;
  33. /**
  34. * Authorization plugin designed to work with the MultiAuthPlugin to support different
  35. * AuthorizationPlugin per scheme.
  36. *
  37. * @lucene.experimental
  38. */
  39. public class MultiAuthRuleBasedAuthorizationPlugin extends RuleBasedAuthorizationPluginBase {
  40. private final Map<String, RuleBasedAuthorizationPluginBase> pluginMap = new LinkedHashMap<>();
  41. private final ResourceLoader loader;
  42. // Need the CC to get the resource loader for loading the sub-plugins
  43. public MultiAuthRuleBasedAuthorizationPlugin(CoreContainer cc) {
  44. this.loader = cc.getResourceLoader();
  45. }
  46. @Override
  47. @SuppressWarnings({"unchecked"})
  48. public void init(Map<String, Object> initInfo) {
  49. super.init(initInfo);
  50. Object o = initInfo.get(MultiAuthPlugin.PROPERTY_SCHEMES);
  51. if (!(o instanceof List)) {
  52. throw new SolrException(
  53. SolrException.ErrorCode.SERVER_ERROR,
  54. "Invalid config: " + getClass().getName() + " requires a list of schemes!");
  55. }
  56. List<Object> schemeList = (List<Object>) o;
  57. if (schemeList.size() < 2) {
  58. throw new SolrException(
  59. SolrException.ErrorCode.SERVER_ERROR,
  60. "Invalid config: " + getClass().getName() + " requires at least two schemes!");
  61. }
  62. for (Object s : schemeList) {
  63. if (!(s instanceof Map)) {
  64. throw new SolrException(
  65. SolrException.ErrorCode.SERVER_ERROR,
  66. "Invalid scheme config, expected JSON object but found: " + s);
  67. }
  68. initPluginForScheme((Map<String, Object>) s);
  69. }
  70. }
  71. protected void initPluginForScheme(Map<String, Object> schemeMap) {
  72. Map<String, Object> schemeConfig = new HashMap<>(schemeMap);
  73. String scheme = (String) schemeConfig.remove(MultiAuthPlugin.PROPERTY_SCHEME);
  74. if (StringUtils.isEmpty(scheme)) {
  75. throw new SolrException(
  76. SolrException.ErrorCode.SERVER_ERROR, "'scheme' is a required attribute: " + schemeMap);
  77. }
  78. String clazz = (String) schemeConfig.remove("class");
  79. if (StringUtils.isEmpty(clazz)) {
  80. throw new SolrException(
  81. SolrException.ErrorCode.SERVER_ERROR, "'class' is a required attribute: " + schemeMap);
  82. }
  83. RuleBasedAuthorizationPluginBase pluginForScheme =
  84. loader.newInstance(clazz, RuleBasedAuthorizationPluginBase.class);
  85. pluginForScheme.init(schemeConfig);
  86. pluginMap.put(scheme.toLowerCase(Locale.ROOT), pluginForScheme);
  87. }
  88. /**
  89. * Pulls roles from the Principal
  90. *
  91. * @param principal the user Principal which should contain roles
  92. * @return set of roles as strings
  93. */
  94. @Override
  95. public Set<String> getUserRoles(Principal principal) {
  96. Set<String> mergedRoles = new HashSet<>();
  97. for (RuleBasedAuthorizationPluginBase plugin : pluginMap.values()) {
  98. final Set<String> userRoles = plugin.getUserRoles(principal);
  99. if (userRoles != null) {
  100. mergedRoles.addAll(userRoles);
  101. }
  102. }
  103. return mergedRoles;
  104. }
  105. @Override
  106. public Map<String, Object> edit(Map<String, Object> latestConf, List<CommandOperation> commands) {
  107. boolean madeChanges = false;
  108. for (CommandOperation c : commands) {
  109. // just let the base class handle permission commands
  110. if (c.name.endsWith("-permission")) {
  111. Map<String, Object> updated = super.edit(latestConf, Collections.singletonList(c));
  112. if (updated != null) {
  113. madeChanges = true;
  114. latestConf = updated;
  115. }
  116. continue;
  117. }
  118. Map<String, Object> dataMap = c.getDataMap();
  119. // expect the "scheme" wrapper map around the actual command data
  120. if (dataMap == null || dataMap.size() != 1) {
  121. throw new SolrException(
  122. SolrException.ErrorCode.BAD_REQUEST,
  123. "All edit commands must include a 'scheme' wrapper object!");
  124. }
  125. final String scheme = dataMap.keySet().iterator().next().toLowerCase(Locale.ROOT);
  126. RuleBasedAuthorizationPluginBase plugin = pluginMap.get(scheme);
  127. if (plugin == null) {
  128. throw new SolrException(
  129. SolrException.ErrorCode.BAD_REQUEST,
  130. "No authorization plugin configured for the '"
  131. + scheme
  132. + "' scheme! Did you forget to wrap the command with a scheme object?");
  133. }
  134. CommandOperation cmdForPlugin = new CommandOperation(c.name, dataMap.get(scheme));
  135. if (applyEditCommandToSchemePlugin(scheme, plugin, cmdForPlugin, latestConf)) {
  136. madeChanges = true;
  137. }
  138. // copy over any errors from the cloned command
  139. for (String err : cmdForPlugin.getErrors()) {
  140. c.addError(err);
  141. }
  142. }
  143. return madeChanges ? latestConf : null;
  144. }
  145. }