From a5c73d39d3f940b6fe5d4b21bee89fab65bce10a Mon Sep 17 00:00:00 2001 From: Mike Drob Date: Fri, 1 May 2020 13:09:28 -0500 Subject: [PATCH] Revert "SOLR-14440 CertAuth plugin (#1463)" Another commit accidentally snuck in This reverts commit 7b289d6185f30b316d07d5ae5755cfc70c97921d. --- solr/CHANGES.txt | 2 +- .../solr/metrics/SolrMetricManager.java | 47 ++++------- .../apache/solr/security/CertAuthPlugin.java | 51 ------------ .../solr/servlet/SolrDispatchFilter.java | 2 +- .../solr/security/CertAuthPluginTest.java | 79 ------------------- ...hentication-and-authorization-plugins.adoc | 2 +- .../src/cert-authentication-plugin.adoc | 61 -------------- solr/solr-ref-guide/src/securing-solr.adoc | 1 - .../web/js/angular/controllers/login.js | 2 +- solr/webapp/web/partials/login.html | 17 ---- 10 files changed, 20 insertions(+), 244 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/security/CertAuthPlugin.java delete mode 100644 solr/core/src/test/org/apache/solr/security/CertAuthPluginTest.java delete mode 100644 solr/solr-ref-guide/src/cert-authentication-plugin.adoc diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 50f2614aec1..3282f7c7897 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -10,7 +10,7 @@ Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this r New Features --------------------- -* SOLR-14440: Introduce new Certificate Authentication Plugin to load Principal from certificate subject. (Mike Drob) +(No changes) Improvements ---------------------- diff --git a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java index 517f8dd3f76..14843ba02e9 100644 --- a/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java +++ b/solr/core/src/java/org/apache/solr/metrics/SolrMetricManager.java @@ -527,12 +527,11 @@ public class SolrMetricManager { */ public enum ResolutionStrategy { /** - * The existing metric will be kept and the new metric will be ignored. If no metric exists, then the new metric - * will be registered. + * The existing metric will be kept and the new metric will be ignored */ IGNORE, /** - * The existing metric will be removed and replaced with the new metric. + * The existing metric will be removed and replaced with the new metric */ REPLACE, /** @@ -557,11 +556,13 @@ public class SolrMetricManager { Map existingMetrics = metricRegistry.getMetrics(); for (Map.Entry entry : metrics.getMetrics().entrySet()) { String fullName = mkName(entry.getKey(), metricPath); - if (strategy == ResolutionStrategy.REPLACE) { - metricRegistry.remove(fullName); - } else if (strategy == ResolutionStrategy.IGNORE && existingMetrics.containsKey(fullName)) { - continue; - } // strategy == ERROR will fail when we try to register + if (existingMetrics.containsKey(fullName)) { + if (strategy == ResolutionStrategy.REPLACE) { + metricRegistry.remove(fullName); + } else if (strategy == ResolutionStrategy.IGNORE) { + continue; + } // strategy == ERROR will fail when we try to register later + } metricRegistry.register(fullName, entry.getValue()); } } @@ -683,36 +684,28 @@ public class SolrMetricManager { return registry(registry).histogram(name, histogramSupplier); } - /** - * @deprecated use {@link #registerMetric(SolrMetricsContext, String, Metric, ResolutionStrategy, String, String...)} - */ - @Deprecated - public void registerMetric(SolrMetricsContext context, String registry, Metric metric, boolean force, String metricName, String... metricPath) { - registerMetric(context, registry, metric, force ? ResolutionStrategy.REPLACE : ResolutionStrategy.IGNORE, metricName, metricPath); - } - /** * Register an instance of {@link Metric}. * * @param registry registry name * @param metric metric instance - * @param strategy the conflict resolution strategy to use if the named metric already exists. + * @param force if true then an already existing metric with the same name will be replaced. + * When false and a metric with the same name already exists an exception + * will be thrown. * @param metricName metric name, either final name or a fully-qualified name * using dotted notation * @param metricPath (optional) additional top-most metric name path elements */ - public void registerMetric(SolrMetricsContext context, String registry, Metric metric, ResolutionStrategy strategy, String metricName, String... metricPath) { + public void registerMetric(SolrMetricsContext context, String registry, Metric metric, boolean force, String metricName, String... metricPath) { MetricRegistry metricRegistry = registry(registry); String fullName = mkName(metricName, metricPath); if (context != null) { context.registerMetricName(fullName); } synchronized (metricRegistry) { // prevent race; register() throws if metric is already present - if (strategy == ResolutionStrategy.REPLACE) { // must remove any existing one if present + if (force) { // must remove any existing one if present metricRegistry.remove(fullName); - } else if (strategy == ResolutionStrategy.IGNORE && metricRegistry.getMetrics().containsKey(fullName)) { - return; - } // strategy == ERROR will fail when we try to register + } metricRegistry.register(fullName, metric); } } @@ -747,16 +740,8 @@ public class SolrMetricManager { } } - /** - * @deprecated use {@link #registerGauge(SolrMetricsContext, String, Gauge, String, ResolutionStrategy, String, String...)} - */ - @Deprecated public void registerGauge(SolrMetricsContext context, String registry, Gauge gauge, String tag, boolean force, String metricName, String... metricPath) { - registerGauge(context, registry, gauge, tag, force ? ResolutionStrategy.REPLACE : ResolutionStrategy.ERROR, metricName, metricPath); - } - - public void registerGauge(SolrMetricsContext context, String registry, Gauge gauge, String tag, ResolutionStrategy strategy, String metricName, String... metricPath) { - registerMetric(context, registry, new GaugeWrapper(gauge, tag), strategy, metricName, metricPath); + registerMetric(context, registry, new GaugeWrapper(gauge, tag), force, metricName, metricPath); } public int unregisterGauges(String registryName, String tagSegment) { diff --git a/solr/core/src/java/org/apache/solr/security/CertAuthPlugin.java b/solr/core/src/java/org/apache/solr/security/CertAuthPlugin.java deleted file mode 100644 index 765aa894f36..00000000000 --- a/solr/core/src/java/org/apache/solr/security/CertAuthPlugin.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 org.apache.http.HttpHeaders; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.security.cert.X509Certificate; -import java.util.Map; - -/** - * An authentication plugin that sets principal based on the certificate subject - */ -public class CertAuthPlugin extends AuthenticationPlugin { - @Override - public void init(Map pluginConfig) { - - } - - @Override - public boolean doAuthenticate(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws Exception { - X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); - if (certs == null || certs.length == 0) { - numMissingCredentials.inc(); - response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Certificate"); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "require certificate"); - return false; - } - - HttpServletRequest wrapped = wrapWithPrincipal(request, certs[0].getSubjectX500Principal()); - numAuthenticated.inc(); - filterChain.doFilter(wrapped, response); - return true; - } -} diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java index 3cee4a1940f..eb2f74a8f86 100644 --- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java +++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java @@ -226,7 +226,7 @@ public class SolrDispatchFilter extends BaseSolrFilter { } }); }); - metricManager.registerGauge(null, registryName, sysprops, metricTag, SolrMetricManager.ResolutionStrategy.IGNORE, "properties", "system"); + metricManager.registerGauge(null, registryName, sysprops, metricTag, true, "properties", "system"); } catch (Exception e) { log.warn("Error registering JVM metrics", e); } diff --git a/solr/core/src/test/org/apache/solr/security/CertAuthPluginTest.java b/solr/core/src/test/org/apache/solr/security/CertAuthPluginTest.java deleted file mode 100644 index fb32a217cea..00000000000 --- a/solr/core/src/test/org/apache/solr/security/CertAuthPluginTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 org.apache.solr.SolrTestCaseJ4; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import javax.security.auth.x500.X500Principal; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.security.cert.X509Certificate; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class CertAuthPluginTest extends SolrTestCaseJ4 { - private CertAuthPlugin plugin; - - @BeforeClass - public static void setupMockito() { - SolrTestCaseJ4.assumeWorkingMockito(); - } - - @Before - public void setUp() throws Exception { - super.setUp(); - plugin = new CertAuthPlugin(); - } - - @Test - public void testAuthenticateOk() throws Exception { - X500Principal principal = new X500Principal("CN=NAME"); - X509Certificate certificate = mock(X509Certificate.class); - HttpServletRequest request = mock(HttpServletRequest.class); - - when(certificate.getSubjectX500Principal()).thenReturn(principal); - when(request.getAttribute(any())).thenReturn(new X509Certificate[] { certificate }); - - FilterChain chain = (req, rsp) -> assertEquals(principal, ((HttpServletRequest) req).getUserPrincipal()); - assertTrue(plugin.doAuthenticate(request, null, chain)); - - assertEquals(1, plugin.numAuthenticated.getCount()); - } - - @Test - public void testAuthenticateMissing() throws Exception { - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getAttribute(any())).thenReturn(null); - - HttpServletResponse response = mock(HttpServletResponse.class); - - assertFalse(plugin.doAuthenticate(request, response, null)); - verify(response).sendError(eq(401), anyString()); - - assertEquals(1, plugin.numMissingCredentials.getCount()); - } -} diff --git a/solr/solr-ref-guide/src/authentication-and-authorization-plugins.adoc b/solr/solr-ref-guide/src/authentication-and-authorization-plugins.adoc index 4e4a8c3ce7d..b8f9a3d6196 100644 --- a/solr/solr-ref-guide/src/authentication-and-authorization-plugins.adoc +++ b/solr/solr-ref-guide/src/authentication-and-authorization-plugins.adoc @@ -1,5 +1,5 @@ = Configuring Authentication, Authorization and Audit Logging -:page-children: basic-authentication-plugin, hadoop-authentication-plugin, kerberos-authentication-plugin, jwt-authentication-plugin, cert-authentication-plugin, rule-based-authorization-plugin, audit-logging +:page-children: basic-authentication-plugin, hadoop-authentication-plugin, kerberos-authentication-plugin, jwt-authentication-plugin, rule-based-authorization-plugin, audit-logging // 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 diff --git a/solr/solr-ref-guide/src/cert-authentication-plugin.adoc b/solr/solr-ref-guide/src/cert-authentication-plugin.adoc deleted file mode 100644 index 4b23cc98604..00000000000 --- a/solr/solr-ref-guide/src/cert-authentication-plugin.adoc +++ /dev/null @@ -1,61 +0,0 @@ -= Certificate Authentication Plugin -// 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. - -Solr can support extracting the user principal out of the client's certificate with the use of the CertAuthPlugin. - -== Enable Certificate Authentication - -For Certificate authentication, the `security.json` file must have an `authentication` part which defines the class being used for authentication. - -An example `security.json` is shown below: - -[source,json] ----- -{ - "authentication": { - "class":"solr.CertAuthPlugin" - } -} ----- - -=== Certificate Validation - -Parts of certificate validation, including verifying the trust chain and peer hostname/ip address will be done by the web servlet container before the request ever reaches the authentication plugin. -These checks are described in the <> section. - -This plugin provides no additional checking beyond what has been configured via SSL properties. - -=== User Principal Extraction - -This plugin will configure the user principal for the request based on the X500 subject present in the client certificate. -Authorization plugins will need to accept and handle the full subject name, for example: - -[source] ----- -CN=Solr User,OU=Engineering,O=Example Inc.,C=US ----- - -A list of possible tags that can be present in the subject name is available in https://tools.ietf.org/html/rfc5280#section-4.1.2.4[RFC-5280, Section 4.1.2.4]. Values may have spaces, punctuation, and other characters. - -It is best practice to verify the actual contents of certificates issued by your trusted certificate authority before configuring authorization based on the contents. - -== Using Certificate Auth with Clients (including SolrJ) - -With certificate authentication enabled, all client requests must include a valid certificate. -This is identical to the <> when using SSL. - diff --git a/solr/solr-ref-guide/src/securing-solr.adoc b/solr/solr-ref-guide/src/securing-solr.adoc index 1d3baee532f..c3e17e9d982 100644 --- a/solr/solr-ref-guide/src/securing-solr.adoc +++ b/solr/solr-ref-guide/src/securing-solr.adoc @@ -44,7 +44,6 @@ Authentication makes sure you know the identity of your users. The authenticatio * <> * <> * <> -* <> // end::list-of-authentication-plugins[] === Authorization Plugins diff --git a/solr/webapp/web/js/angular/controllers/login.js b/solr/webapp/web/js/angular/controllers/login.js index b76ec1f4a8a..8127c6fdac0 100644 --- a/solr/webapp/web/js/angular/controllers/login.js +++ b/solr/webapp/web/js/angular/controllers/login.js @@ -47,7 +47,7 @@ solrAdminApp.controller('LoginController', sessionStorage.setItem("auth.scheme", authScheme); } - var supportedSchemes = ['Basic', 'Bearer', 'Negotiate', 'Certificate']; + var supportedSchemes = ['Basic', 'Bearer', 'Negotiate']; $scope.authSchemeSupported = supportedSchemes.includes(authScheme); if (authScheme === 'Bearer') { diff --git a/solr/webapp/web/partials/login.html b/solr/webapp/web/partials/login.html index c21f2622295..29c8c71501b 100644 --- a/solr/webapp/web/partials/login.html +++ b/solr/webapp/web/partials/login.html @@ -76,23 +76,6 @@ limitations under the License. WWW-Authenticate: {{wwwAuthHeader}}
- -
-

Certificate Authentication

-

Your browser did not provide the required information to authenticate using PKI Certificates. - Please check that your computer has a valid PKI certificate for communicating with Solr, - and that your browser is properly configured to provide that certificate when required. - For more information, consult - - Solr's Certificate Authentication documentation - . -

- The response from the server was: -
-
HTTP 401 {{statusText}}
-WWW-Authenticate: {{wwwAuthHeader}}
-
-

OpenID Connect (JWT) authentication