diff --git a/agents-audit/dest-solr/pom.xml b/agents-audit/dest-solr/pom.xml index b9e562ca065..70185f10eed 100644 --- a/agents-audit/dest-solr/pom.xml +++ b/agents-audit/dest-solr/pom.xml @@ -67,6 +67,11 @@ ranger-audit-core ${project.version} + + org.apache.solr + solr-api + ${solr.version} + org.apache.solr solr-solrj diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerJersey2ClientBuilder.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerJersey2ClientBuilder.java index 714412c88bd..2fada121981 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerJersey2ClientBuilder.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerJersey2ClientBuilder.java @@ -19,7 +19,6 @@ package org.apache.ranger.plugin.util; -import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.slf4j.Logger; @@ -30,6 +29,9 @@ import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + /** * Comprehensive Jersey client utility for Ranger components. * @@ -67,6 +69,12 @@ public class RangerJersey2ClientBuilder { // Configuration constants private static final String DISABLE_AUTO_DISCOVERY_PROPERTY = "jersey.config.disableAutoDiscovery"; private static final String PROVIDER_SCANNING_RECURSIVE_PROPERTY = "jersey.config.server.provider.scanning.recursive"; + private static final String JERSEY_JACKSON_FEATURE_CLASS = "org.glassfish.jersey.jackson.JacksonFeature"; + private static final String[] JACKSON_JSON_PROVIDER_CLASSES = { + "org.glassfish.jersey.jackson.internal.DefaultJacksonJaxbJsonProvider", + "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider", + }; + private static final String RANGER_PLUGIN_CLASSLOADER_CLASS = "org.apache.ranger.plugin.classloader.RangerPluginClassLoader"; private static final int DEFAULT_CONNECT_TIMEOUT_MS = 5000; private static final int DEFAULT_READ_TIMEOUT_MS = 30000; @@ -75,6 +83,18 @@ private RangerJersey2ClientBuilder() { // Utility class - no instances } + public static ClientConfig newClientConfig() { + ClassLoader jerseyCl = resolveJerseyClassLoader(); + + try { + Class configClass = Class.forName("org.glassfish.jersey.client.ClientConfig", true, jerseyCl); + + return ClientConfig.class.cast(configClass.getDeclaredConstructor().newInstance()); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException("Failed to create ClientConfig using classloader " + jerseyCl, e); + } + } + /** * Creates a standard Jersey client with MOXy prevention and default timeouts. * @@ -92,23 +112,21 @@ public static Client createStandardClient() { * @return A configured Jersey client safe from MOXy interference */ public static Client createClient(int connectTimeoutMs, int readTimeoutMs) { - LOG.debug("Creating standard Jersey client with timeouts: connect={}ms, read={}ms", connectTimeoutMs, readTimeoutMs); - - ClientConfig config = new ClientConfig(); - applyAntiMoxyConfiguration(config); + return runWithJerseyClassLoader(() -> { + LOG.debug("Creating standard Jersey client with timeouts: connect={}ms, read={}ms", connectTimeoutMs, readTimeoutMs); - // Set timeouts - config.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); - config.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); + ClientConfig config = newClientConfig(); + applyAntiMoxyConfiguration(config); - // Create client with configuration - Client client = ClientBuilder.newClient(config); + config.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); + config.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); - // Validate configuration - validateAntiMoxyConfiguration(config); + Client client = ClientBuilder.newClient(config); + validateAntiMoxyConfiguration(config); - LOG.debug("Successfully created standard Jersey client"); - return client; + LOG.debug("Successfully created standard Jersey client"); + return client; + }); } /** @@ -121,37 +139,33 @@ public static Client createClient(int connectTimeoutMs, int readTimeoutMs) { * @return A configured secure Jersey client safe from MOXy interference */ public static Client createSecureClient(SSLContext sslContext, HostnameVerifier hostnameVerifier, int connectTimeoutMs, int readTimeoutMs) { - LOG.debug("Creating secure Jersey client with SSL - connect={}ms, read={}ms", connectTimeoutMs, readTimeoutMs); + return runWithJerseyClassLoader(() -> { + LOG.debug("Creating secure Jersey client with SSL - connect={}ms, read={}ms", connectTimeoutMs, readTimeoutMs); - ClientConfig config = new ClientConfig(); - applyAntiMoxyConfiguration(config); + ClientConfig config = newClientConfig(); + applyAntiMoxyConfiguration(config); - // Set timeouts - config.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); - config.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); + config.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); + config.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); - // Create builder with configuration - ClientBuilder builder = ClientBuilder.newBuilder().withConfig(config); + ClientBuilder builder = ClientBuilder.newBuilder().withConfig(config); - // Configure SSL if provided - if (sslContext != null) { - builder.sslContext(sslContext); - LOG.debug("Applied custom SSL context"); - } - - if (hostnameVerifier != null) { - builder.hostnameVerifier(hostnameVerifier); - LOG.debug("Applied custom hostname verifier"); - } + if (sslContext != null) { + builder.sslContext(sslContext); + LOG.debug("Applied custom SSL context"); + } - // Build client - Client client = builder.build(); + if (hostnameVerifier != null) { + builder.hostnameVerifier(hostnameVerifier); + LOG.debug("Applied custom hostname verifier"); + } - // Validate configuration - validateAntiMoxyConfiguration(config); + Client client = builder.build(); + validateAntiMoxyConfiguration(config); - LOG.debug("Successfully created secure Jersey client"); - return client; + LOG.debug("Successfully created secure Jersey client"); + return client; + }); } // ========== DROP-IN REPLACEMENTS for unsafe ClientBuilder patterns ========== @@ -257,37 +271,80 @@ public SafeClientBuilder withConfig(ClientConfig config) { * @return A configured Jersey client safe from MOXy interference */ public Client build() { - if (clientConfig != null) { - // Apply anti-MOXy configuration to the provided config - applyAntiMoxyConfiguration(clientConfig); + return runWithJerseyClassLoader(() -> { + if (clientConfig != null) { + applyAntiMoxyConfiguration(clientConfig); - // Set timeouts if not already configured - if (!clientConfig.getProperties().containsKey(ClientProperties.CONNECT_TIMEOUT)) { - clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); - } - if (!clientConfig.getProperties().containsKey(ClientProperties.READ_TIMEOUT)) { - clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); - } + if (!clientConfig.getProperties().containsKey(ClientProperties.CONNECT_TIMEOUT)) { + clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutMs); + } + if (!clientConfig.getProperties().containsKey(ClientProperties.READ_TIMEOUT)) { + clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeoutMs); + } - // Create ClientBuilder with MOXy-safe configuration - ClientBuilder builder = ClientBuilder.newBuilder().withConfig(clientConfig); + ClientBuilder builder = ClientBuilder.newBuilder().withConfig(clientConfig); - if (sslContext != null) { - builder.sslContext(sslContext); - } - if (hostnameVerifier != null) { - builder.hostnameVerifier(hostnameVerifier); - } + if (sslContext != null) { + builder.sslContext(sslContext); + } + if (hostnameVerifier != null) { + builder.hostnameVerifier(hostnameVerifier); + } - // Validate configuration before building - validateAntiMoxyConfiguration(clientConfig); + validateAntiMoxyConfiguration(clientConfig); + + return builder.build(); + } - return builder.build(); - } else { - // Use the standard secure client creation method return createSecureClient(sslContext, hostnameVerifier, connectTimeoutMs, readTimeoutMs); + }); + } + } + + /** + * Runs Jersey client construction with the host (e.g. Solr webapp) classloader when the + * Ranger plugin classloader is active, so Jersey types are not split across loaders. + */ + public static T runWithJerseyClassLoader(Callable action) { + ClassLoader jerseyCl = resolveJerseyClassLoader(); + ClassLoader previous = Thread.currentThread().getContextClassLoader(); + + try { + Thread.currentThread().setContextClassLoader(jerseyCl); + return action.call(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Failed to build Jersey client using classloader " + jerseyCl, e); + } finally { + Thread.currentThread().setContextClassLoader(previous); + } + } + + static ClassLoader resolveJerseyClassLoader() { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + if (tccl != null && RANGER_PLUGIN_CLASSLOADER_CLASS.equals(tccl.getClass().getName())) { + try { + Method getPrev = tccl.getClass().getMethod("getPrevActiveClassLoader"); + ClassLoader hostCl = (ClassLoader) getPrev.invoke(tccl); + + if (hostCl != null) { + LOG.debug("Using host classloader from RangerPluginClassLoader: {}", hostCl); + return hostCl; + } + } catch (ReflectiveOperationException e) { + LOG.debug("Could not resolve host classloader from RangerPluginClassLoader", e); } } + + ClassLoader fromJerseyApi = ClientConfig.class.getClassLoader(); + + if (fromJerseyApi != null) { + return fromJerseyApi; + } + + return tccl != null ? tccl : RangerJersey2ClientBuilder.class.getClassLoader(); } // ========== VALIDATION AND CONFIGURATION METHODS ========== @@ -317,11 +374,9 @@ public static ClientConfig applyAntiMoxyConfiguration(ClientConfig config) { LOG.debug("Applying anti-MOXy configuration to ClientConfig"); - // 1. Explicitly register Jackson JSON provider with high priority - // Note: JacksonJaxbJsonProvider should be registered with @Priority(1) annotation - config.register(JacksonJaxbJsonProvider.class); + registerJacksonProvider(config); - // 2. Disable Jersey's auto-discovery to prevent MOXy from being found and registered + // Disable Jersey's auto-discovery to prevent MOXy from being found and registered config.property(DISABLE_AUTO_DISCOVERY_PROPERTY, true); config.property(PROVIDER_SCANNING_RECURSIVE_PROPERTY, false); @@ -351,10 +406,7 @@ public static boolean validateAntiMoxyConfiguration(ClientConfig config) { isValid = false; } - // Check if Jackson is registered - boolean jacksonRegistered = config.getClasses().contains(JacksonJaxbJsonProvider.class) || config.getInstances().stream().anyMatch(instance -> instance instanceof JacksonJaxbJsonProvider); - - if (!jacksonRegistered) { + if (!isJacksonProviderRegistered(config)) { LOG.error("CRITICAL: Jackson JSON provider is not registered! Default JSON processing may fail."); isValid = false; } @@ -367,4 +419,61 @@ public static boolean validateAntiMoxyConfiguration(ClientConfig config) { return isValid; } + + private static void registerJacksonProvider(ClientConfig config) { + ClassLoader jerseyCl = config.getClass().getClassLoader(); + Exception lastFailure = null; + + try { + Class featureClass = Class.forName(JERSEY_JACKSON_FEATURE_CLASS, true, jerseyCl); + + config.register(featureClass); + LOG.debug("Registered {} from classloader {}", JERSEY_JACKSON_FEATURE_CLASS, jerseyCl); + return; + } catch (ReflectiveOperationException e) { + lastFailure = e; + LOG.debug("Jersey Jackson feature not available from {}: {}", jerseyCl, e.toString()); + } + + for (String providerClassName : JACKSON_JSON_PROVIDER_CLASSES) { + try { + Class providerClass = Class.forName(providerClassName, true, jerseyCl); + Object provider = providerClass.getDeclaredConstructor().newInstance(); + + config.register(provider); + LOG.debug("Registered {} from classloader {}", providerClassName, jerseyCl); + return; + } catch (ReflectiveOperationException e) { + lastFailure = e; + LOG.debug("Jackson provider {} not available from {}: {}", providerClassName, jerseyCl, e.toString()); + } + } + + throw new IllegalStateException("Failed to register a Jackson JSON provider from classloader " + jerseyCl, lastFailure); + } + + private static boolean isJacksonProviderRegistered(ClientConfig config) { + if (config.getClasses().stream().anyMatch(clazz -> JERSEY_JACKSON_FEATURE_CLASS.equals(clazz.getName()))) { + return true; + } + + for (String providerClassName : JACKSON_JSON_PROVIDER_CLASSES) { + boolean registeredByClass = config.getClasses().stream() + .anyMatch(clazz -> providerClassName.equals(clazz.getName())); + + if (registeredByClass) { + return true; + } + + boolean registeredByInstance = config.getInstances().stream() + .anyMatch(instance -> providerClassName.equals(instance.getClass().getName())); + + if (registeredByInstance) { + return true; + } + } + + return config.getClasses().stream().anyMatch(clazz -> clazz.getName().contains("jersey.jackson")) + || config.getInstances().stream().anyMatch(instance -> instance.getClass().getName().contains("jersey.jackson")); + } } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java index e6996103e16..c26b811fab4 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRESTClient.java @@ -608,8 +608,12 @@ private Client getCookieAuthClient() { } private Client buildClient() { + return RangerJersey2ClientBuilder.runWithJerseyClassLoader(this::buildClientInternal); + } + + private Client buildClientInternal() { RangerJersey2ClientBuilder.SafeClientBuilder clientBuilder; - ClientConfig config = new ClientConfig(); + ClientConfig config = RangerJersey2ClientBuilder.newClientConfig(); if (mIsSSL) { try { diff --git a/audit-server/audit-dispatcher/dispatcher-solr/pom.xml b/audit-server/audit-dispatcher/dispatcher-solr/pom.xml index f519a4e1812..3c4a5c57c08 100644 --- a/audit-server/audit-dispatcher/dispatcher-solr/pom.xml +++ b/audit-server/audit-dispatcher/dispatcher-solr/pom.xml @@ -113,74 +113,74 @@ org.apache.lucene - lucene-analyzers-common - ${lucene.version} + lucene-analysis-common + ${solr.lucene.version} org.apache.lucene lucene-backward-codecs - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-core - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-grouping - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-highlighter - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-join - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-memory - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-misc - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-queries - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-queryparser - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-sandbox - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-spatial-extras - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-spatial3d - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-suggest - ${lucene.version} + ${solr.lucene.version} org.apache.ranger diff --git a/audit-server/pom.xml b/audit-server/pom.xml index 22d246b2d08..01620cac6ea 100644 --- a/audit-server/pom.xml +++ b/audit-server/pom.xml @@ -173,74 +173,74 @@ org.apache.lucene - lucene-analyzers-common - ${lucene.version} + lucene-analysis-common + ${solr.lucene.version} org.apache.lucene lucene-backward-codecs - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-core - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-grouping - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-highlighter - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-join - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-memory - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-misc - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-queries - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-queryparser - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-sandbox - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-spatial-extras - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-spatial3d - ${lucene.version} + ${solr.lucene.version} org.apache.lucene lucene-suggest - ${lucene.version} + ${solr.lucene.version} diff --git a/dev-support/checks/coverage.sh b/dev-support/checks/coverage.sh index eabf0a4a330..90e13399516 100755 --- a/dev-support/checks/coverage.sh +++ b/dev-support/checks/coverage.sh @@ -49,6 +49,10 @@ find . -type d -name 'target' -prune -exec find {} -type f \( -name 'ranger-*.ja -or -name '*shim*' -prune \ | xargs -n1 unzip -o -q -d target/coverage-classes +# Lucene 9+ (Solr 9) ships multi-release classes under META-INF/versions/*; JaCoCo 0.8.x +# fails with "Can't add different class with same name" when both base and versioned copies exist. +rm -rf target/coverage-classes/META-INF/versions + # get all source file paths src=$(find . -path '*/src/main/java' -o -path './target' -prune | sed 's/^/--sourcefiles /g' | xargs echo) diff --git a/dev-support/ranger-docker/.env b/dev-support/ranger-docker/.env index 12d2777ec01..144b698ab0b 100644 --- a/dev-support/ranger-docker/.env +++ b/dev-support/ranger-docker/.env @@ -54,7 +54,7 @@ TAGSYNC_VERSION=3.0.0-SNAPSHOT PDP_VERSION=3.0.0-SNAPSHOT # Solr Configuration -SOLR_VERSION=8.11.3 +SOLR_VERSION=9.4.1 SOLR_PLUGIN_VERSION=3.0.0-SNAPSHOT # Zookeeper Configuration diff --git a/dev-support/ranger-docker/Dockerfile.ranger-solr b/dev-support/ranger-docker/Dockerfile.ranger-solr index 2bb4fa824e9..b4984e202e1 100644 --- a/dev-support/ranger-docker/Dockerfile.ranger-solr +++ b/dev-support/ranger-docker/Dockerfile.ranger-solr @@ -15,8 +15,8 @@ # limitations under the License. ARG RANGER_BASE_IMAGE=apache/ranger-base -ARG RANGER_BASE_VERSION=20260123-2-8 -ARG SOLR_VERSION=8.11.3 +ARG RANGER_BASE_VERSION=20260123-2-17 +ARG SOLR_VERSION=9.4.1 FROM ${RANGER_BASE_IMAGE}:${RANGER_BASE_VERSION} AS ranger-base FROM solr:${SOLR_VERSION} @@ -26,8 +26,15 @@ USER root RUN apt update && DEBIAN_FRONTEND="noninteractive" apt-get install -y krb5-user -RUN mkdir -p /opt/solr/server/solr/configsets/ranger_audits/conf /home/ranger/dist /opt/ranger /home/ranger/scripts -RUN chown -R solr:solr /opt/solr/server/solr/configsets/ranger_audits/ +# Create all necessary directories in one go, including /var/solr/data +RUN mkdir -p /opt/solr/server/solr/configsets/ranger_audits/conf \ + /home/ranger/dist \ + /opt/ranger \ + /home/ranger/scripts \ + /var/solr/data +# Apply ownership to the directories in one go +RUN chown -R solr:solr /opt/solr/server/solr/configsets/ranger_audits/ \ + /var/solr COPY --from=ranger-base /home/ranger/scripts/wait_for_keytab.sh /home/ranger/scripts/wait_for_keytab.sh COPY --from=ranger-base /home/ranger/scripts/wait_for_testusers_keytab.sh /home/ranger/scripts/wait_for_testusers_keytab.sh @@ -42,4 +49,4 @@ RUN tar xvfz /home/ranger/dist/ranger-${SOLR_PLUGIN_VERSION}-solr-plugin.tar.gz chown -R solr:solr /opt/ranger ENTRYPOINT [ "/opt/ranger/ranger-solr.sh" ] -CMD ["solr-foreground"] +CMD ["solr-foreground"] \ No newline at end of file diff --git a/dev-support/ranger-docker/docker-compose.ranger.yml b/dev-support/ranger-docker/docker-compose.ranger.yml index e37469c1098..f3b3b60fc5e 100644 --- a/dev-support/ranger-docker/docker-compose.ranger.yml +++ b/dev-support/ranger-docker/docker-compose.ranger.yml @@ -13,11 +13,11 @@ services: container_name: ranger hostname: ranger.rangernw volumes: - - ./dist/keytabs/ranger:/etc/keytabs + - ./dist/keytabs/ranger:/etc/keytabs:ro - ./dist/version:/home/ranger/dist/version:ro - ./scripts/kdc/krb5.conf:/etc/krb5.conf:ro - ./scripts/hadoop/core-site.xml:/home/ranger/scripts/core-site.xml:ro - - ./scripts/admin/ranger-admin-install-${RANGER_DB_TYPE}.properties:/opt/ranger/admin/install.properties + - ./scripts/admin/ranger-admin-install-${RANGER_DB_TYPE}.properties:/opt/ranger/admin/install.properties:ro stdin_open: true tty: true networks: @@ -82,9 +82,9 @@ services: container_name: ranger-zk hostname: ranger-zk.rangernw volumes: - - ./dist/keytabs/ranger-zk:/etc/keytabs + - ./dist/keytabs/ranger-zk:/etc/keytabs:ro - ./scripts/kdc/krb5.conf:/etc/krb5.conf:ro - - ./scripts/zk/jaas.conf:/etc/zookeeper/jaas.conf + - ./scripts/zk/jaas.conf:/etc/zookeeper/jaas.conf:ro - ./scripts/zk/zookeeper-with-kerberos.sh:/zookeeper-with-kerberos.sh:ro entrypoint: [ "/bin/bash", "/zookeeper-with-kerberos.sh" ] networks: @@ -108,14 +108,19 @@ services: container_name: ranger-solr hostname: ranger-solr.rangernw volumes: - - ./dist/keytabs/ranger-solr:/etc/keytabs - - ./scripts/solr/solr-ranger_audits:/opt/solr/server/solr/configsets/ranger_audits/conf - - ./scripts/solr/ranger-solr-plugin-install.properties:/opt/ranger/ranger-solr-plugin/install.properties - - ./scripts/solr/core-site.xml:/opt/solr/server/resources/core-site.xml - - ./scripts/solr/solr-jaas.conf:/opt/solr/server/etc/jaas.conf - - ./scripts/solr/solr-security.json:/var/solr/data/security.json - - ./scripts/solr/ranger-solr.sh:/opt/ranger/ranger-solr.sh - - ./scripts/kdc/krb5.conf:/etc/krb5.conf + - ./dist/keytabs/ranger-solr:/etc/keytabs:ro + - ./scripts/solr/solr-ranger_audits:/opt/solr/server/solr/configsets/ranger_audits/conf:ro + # Core conf is copied once by solr-precreate; mount so Solr 9 cache updates apply without recreating the core + - ./scripts/solr/solr-ranger_audits:/var/solr/data/ranger_audits/conf:ro + - ./scripts/solr/ranger_audits/core.properties:/var/solr/data/ranger_audits/core.properties:ro + - ./scripts/solr/ranger-solr-plugin-install.properties:/opt/ranger/ranger-solr-plugin/install.properties:ro + # Keep enable templates in sync with repo (image tarball may be stale) + - ../../plugin-solr/conf/ranger-solr-security-changes.cfg:/opt/ranger/ranger-solr-plugin/install/conf.templates/enable/ranger-solr-security-changes.cfg:ro + - ./scripts/solr/core-site.xml:/opt/solr/server/resources/core-site.xml:ro + - ./scripts/solr/solr-jaas.conf:/opt/solr/server/etc/jaas.conf:ro + - ./scripts/solr/solr-security.json:/var/solr/data/security.json:ro + - ./scripts/solr/ranger-solr.sh:/opt/ranger/ranger-solr.sh:ro + - ./scripts/kdc/krb5.conf:/etc/krb5.conf:ro networks: - ranger ports: @@ -128,6 +133,8 @@ services: environment: - KERBEROS_ENABLED - KRB5_CONFIG=/etc/krb5.conf + # Solr 9 enables Java SecurityManager by default; Ranger keytab login and policy cache need broader access + - SOLR_SECURITY_MANAGER_ENABLED=false command: - solr-precreate - ranger_audits diff --git a/dev-support/ranger-docker/scripts/solr/ranger-solr-plugin-install.properties b/dev-support/ranger-docker/scripts/solr/ranger-solr-plugin-install.properties index 2f8b69e4308..b2d17dcee7b 100644 --- a/dev-support/ranger-docker/scripts/solr/ranger-solr-plugin-install.properties +++ b/dev-support/ranger-docker/scripts/solr/ranger-solr-plugin-install.properties @@ -17,7 +17,11 @@ POLICY_MGR_URL=http://ranger.rangernw:6080 REPOSITORY_NAME=dev_solr COMPONENT_INSTALL_DIR_NAME=/opt/solr/server UGI_INITIALIZE=true -UGI_LOGIN_TYPE=jaas +# keytab login: Ranger plugin does not rely on JVM-global JAAS (java.security.auth.login.config) +UGI_LOGIN_TYPE=keytab +UGI_KEYTAB_PRINCIPAL=solr/ranger-solr.rangernw@EXAMPLE.COM +UGI_KEYTAB_FILE=/etc/keytabs/solr.keytab +# Required by security-changes.cfg token even when login.type=keytab (unused for Ranger Admin REST) UGI_JAAS_APPCONFIG=Client XAAUDIT.SOLR.IS_ENABLED=true diff --git a/dev-support/ranger-docker/scripts/solr/ranger-solr.sh b/dev-support/ranger-docker/scripts/solr/ranger-solr.sh index 719e2bee14c..0da2b9244b4 100755 --- a/dev-support/ranger-docker/scripts/solr/ranger-solr.sh +++ b/dev-support/ranger-docker/scripts/solr/ranger-solr.sh @@ -39,14 +39,39 @@ DEFAULT" export SOLR_AUTHENTICATION_OPTS="${JAAS_CONFIG} ${JAAS_APPNAME} ${KRB5_CONF} ${KERBEROS_KEYTAB} ${KERBEROS_PRINCIPAL} ${COOKIE_DOMAIN} ${KERBEROS_NAME_RULES}" export SOLR_AUTH_TYPE=kerberos + export HADOOP_CONF_DIR=/opt/solr/server/resources + export SOLR_AUTHENTICATION_OPTS="${SOLR_AUTHENTICATION_OPTS} -Dhadoop.security.authentication=kerberos" + # Solr 9 docker entrypoint appends SOLR_AUTHENTICATION_OPTS to SOLR_OPTS when SOLR_AUTH_TYPE=kerberos + export SOLR_OPTS="${SOLR_OPTS} ${SOLR_AUTHENTICATION_OPTS}" fi +# Ranger policy cache, keytabs (Solr 9 SecurityManager; allowPaths used when SM is enabled) +export SOLR_OPTS="${SOLR_OPTS} -Dsolr.allowPaths=/etc/ranger,/etc/keytabs" +export SOLR_SECURITY_MANAGER_ENABLED="${SOLR_SECURITY_MANAGER_ENABLED:-false}" +# Solr 9.4+: KerberosPlugin lives in the hadoop-auth module +export SOLR_MODULES="${SOLR_MODULES:+$SOLR_MODULES,}hadoop-auth" + if [ ! -e ${SOLR_INSTALL_DIR}/.setupDone ] then + POLICY_CACHE_DIR=/etc/ranger/dev_solr/policycache + mkdir -p "${POLICY_CACHE_DIR}" + chmod a+rx /etc/ranger /etc/ranger/dev_solr "${POLICY_CACHE_DIR}" 2>/dev/null || true + cd /opt/ranger/ranger-solr-plugin ./enable-solr-plugin.sh touch "${SOLR_INSTALL_DIR}"/.setupDone fi -su -p -c "export PATH=${PATH} && /opt/docker-solr/scripts/docker-entrypoint.sh $*" solr +# conf/ is bind-mounted; solr-precreate may skip writing core.properties when the core dir already exists +RANGER_AUDITS_CORE_DIR=/var/solr/data/ranger_audits +if [ -d "${RANGER_AUDITS_CORE_DIR}/conf" ] && [ ! -f "${RANGER_AUDITS_CORE_DIR}/core.properties" ]; then + printf '%s\n' 'name=ranger_audits' 'config=solrconfig.xml' 'schema=managed-schema' 'dataDir=data' > "${RANGER_AUDITS_CORE_DIR}/core.properties" + mkdir -p "${RANGER_AUDITS_CORE_DIR}/data" +fi +chown -R solr:solr "${RANGER_AUDITS_CORE_DIR}" 2>/dev/null || true + +export PATH="/opt/solr/bin:/opt/solr/docker/scripts:/opt/solr/prometheus-exporter/bin:${PATH}" +export HADOOP_CONF_DIR="${HADOOP_CONF_DIR:-/opt/solr/server/resources}" +su -p -c "export PATH=${PATH} HADOOP_CONF_DIR=${HADOOP_CONF_DIR} SOLR_SECURITY_MANAGER_ENABLED=${SOLR_SECURITY_MANAGER_ENABLED:-false} SOLR_OPTS=\"${SOLR_OPTS}\" SOLR_AUTHENTICATION_OPTS=\"${SOLR_AUTHENTICATION_OPTS}\" && /opt/solr/docker/scripts/docker-entrypoint.sh $*" solr +#su -p -c "export PATH=${PATH} && /opt/docker-solr/scripts/docker-entrypoint.sh $*" solr diff --git a/dev-support/ranger-docker/scripts/solr/ranger_audits/core.properties b/dev-support/ranger-docker/scripts/solr/ranger_audits/core.properties new file mode 100644 index 00000000000..090fe4a98c5 --- /dev/null +++ b/dev-support/ranger-docker/scripts/solr/ranger_audits/core.properties @@ -0,0 +1,5 @@ +# Solr 9 instance dir marker (required for CorePropertiesLocator) +name=ranger_audits +config=solrconfig.xml +schema=managed-schema +dataDir=data diff --git a/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/managed-schema b/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/managed-schema index eabb5f8fdb8..88484fd5d29 100644 --- a/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/managed-schema +++ b/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/managed-schema @@ -1,45 +1,30 @@ - + id - - - - - - - + + + + + + + - + - + - - - - - + + + + + @@ -50,13 +35,13 @@ - - - - - - - + + + + + + + @@ -66,33 +51,34 @@ - + + - + + + - - + + + - + + - - - - - + \ No newline at end of file diff --git a/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/solrconfig.xml b/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/solrconfig.xml index 33891833c4a..b95af165183 100644 --- a/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/solrconfig.xml +++ b/dev-support/ranger-docker/scripts/solr/solr-ranger_audits/solrconfig.xml @@ -417,7 +417,7 @@ to occupy. Note that when this option is specified, the size and initialSize parameters are ignored. --> - @@ -429,7 +429,7 @@ maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed to occupy --> - @@ -439,14 +439,14 @@ document). Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - commons-logging:commons-logging commons-collections:commons-collections commons-io:commons-io + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.httpcomponents:httpclient:jar:${httpcomponents.httpclient.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} diff --git a/distro/src/main/assembly/hbase-agent.xml b/distro/src/main/assembly/hbase-agent.xml index 0431bb5f8e5..a6d1c44d585 100644 --- a/distro/src/main/assembly/hbase-agent.xml +++ b/distro/src/main/assembly/hbase-agent.xml @@ -70,6 +70,7 @@ org.apache.hadoop.thirdparty:hadoop-shaded-guava:jar:${hadoop-shaded-guava.version} org.apache.httpcomponents:httpasyncclient:jar:${httpcomponents.httpasyncclient.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.jersey.core:jersey-client diff --git a/distro/src/main/assembly/hdfs-agent.xml b/distro/src/main/assembly/hdfs-agent.xml index afad632e5d1..bb382e45e86 100644 --- a/distro/src/main/assembly/hdfs-agent.xml +++ b/distro/src/main/assembly/hdfs-agent.xml @@ -100,6 +100,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.jersey.core:jersey-client diff --git a/distro/src/main/assembly/hive-agent.xml b/distro/src/main/assembly/hive-agent.xml index c95e38ee3cf..0530df132cd 100644 --- a/distro/src/main/assembly/hive-agent.xml +++ b/distro/src/main/assembly/hive-agent.xml @@ -79,6 +79,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.jersey.core:jersey-client diff --git a/distro/src/main/assembly/kms.xml b/distro/src/main/assembly/kms.xml index 89e912d8a5d..36ee4e10827 100755 --- a/distro/src/main/assembly/kms.xml +++ b/distro/src/main/assembly/kms.xml @@ -226,6 +226,7 @@ org.apache.hadoop:hadoop-auth:jar:${hadoop.version} org.apache.hadoop:hadoop-client-api:jar:${hadoop.version} org.apache.hadoop:hadoop-client-runtime:jar:${hadoop.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.ranger:ranger-common-utils org.apache.ranger:ranger-authz-api @@ -319,6 +320,7 @@ org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} org.apache.zookeeper:zookeeper:jar:${zookeeper.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpasyncclient:jar:${httpcomponents.httpasyncclient.version} diff --git a/distro/src/main/assembly/knox-agent.xml b/distro/src/main/assembly/knox-agent.xml index f4ff06e9e14..e91077f1b29 100644 --- a/distro/src/main/assembly/knox-agent.xml +++ b/distro/src/main/assembly/knox-agent.xml @@ -77,6 +77,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} diff --git a/distro/src/main/assembly/pdp.xml b/distro/src/main/assembly/pdp.xml index 3aa90ff4f13..267f64cdad1 100644 --- a/distro/src/main/assembly/pdp.xml +++ b/distro/src/main/assembly/pdp.xml @@ -119,6 +119,7 @@ com.fasterxml.woodstox:woodstox-core:jar:${fasterxml.woodstox.version} + org.apache.solr:solr-api org.apache.solr:solr-solrj org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} org.apache.httpcomponents:httpclient:jar:${httpcomponents.httpclient.version} diff --git a/distro/src/main/assembly/plugin-atlas.xml b/distro/src/main/assembly/plugin-atlas.xml index a53a909fdbc..17903c8b28c 100644 --- a/distro/src/main/assembly/plugin-atlas.xml +++ b/distro/src/main/assembly/plugin-atlas.xml @@ -74,6 +74,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.codehaus.woodstox:stax2-api:jar:${codehaus.woodstox.stax2api.version} diff --git a/distro/src/main/assembly/plugin-elasticsearch.xml b/distro/src/main/assembly/plugin-elasticsearch.xml index 5d13459ceb1..bb28c5b1d59 100644 --- a/distro/src/main/assembly/plugin-elasticsearch.xml +++ b/distro/src/main/assembly/plugin-elasticsearch.xml @@ -91,6 +91,7 @@ org.apache.lucene:lucene-core org.apache.orc:orc-core:jar:${orc.version} org.apache.orc:orc-shims:jar:${orc.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.elasticsearch.client:elasticsearch-rest-client diff --git a/distro/src/main/assembly/plugin-kafka.xml b/distro/src/main/assembly/plugin-kafka.xml index 84ed69c16d9..b7d20e1e0a5 100644 --- a/distro/src/main/assembly/plugin-kafka.xml +++ b/distro/src/main/assembly/plugin-kafka.xml @@ -80,6 +80,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.codehaus.woodstox:stax2-api org.eclipse.jetty:jetty-client:jar:${jetty-client.version} diff --git a/distro/src/main/assembly/plugin-kms.xml b/distro/src/main/assembly/plugin-kms.xml index 40537739730..28dd238209f 100755 --- a/distro/src/main/assembly/plugin-kms.xml +++ b/distro/src/main/assembly/plugin-kms.xml @@ -73,6 +73,7 @@ org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} org.apache.orc:orc-core:jar:${orc.version} org.apache.orc:orc-shims:jar:${orc.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.zookeeper:zookeeper:jar:${zookeeper.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} diff --git a/distro/src/main/assembly/plugin-kylin.xml b/distro/src/main/assembly/plugin-kylin.xml index 5c8e1102236..94e9e7025e0 100644 --- a/distro/src/main/assembly/plugin-kylin.xml +++ b/distro/src/main/assembly/plugin-kylin.xml @@ -74,6 +74,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.hk2.external:jakarta.inject diff --git a/distro/src/main/assembly/plugin-ozone.xml b/distro/src/main/assembly/plugin-ozone.xml index 8c534d10c80..d1c7db068a5 100644 --- a/distro/src/main/assembly/plugin-ozone.xml +++ b/distro/src/main/assembly/plugin-ozone.xml @@ -95,6 +95,7 @@ org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.zookeeper:zookeeper:jar:${zookeeper.version} org.apache.zookeeper:zookeeper-jute:jar:${zookeeper.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} com.fasterxml.woodstox:woodstox-core:jar:${fasterxml.woodstox.version} org.codehaus.woodstox:stax2-api:jar:${codehaus.woodstox.stax2api.version} diff --git a/distro/src/main/assembly/plugin-presto.xml b/distro/src/main/assembly/plugin-presto.xml index 493a384451a..1a110ba3157 100644 --- a/distro/src/main/assembly/plugin-presto.xml +++ b/distro/src/main/assembly/plugin-presto.xml @@ -94,6 +94,7 @@ org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} org.apache.ranger:ranger-plugins-cred + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.zookeeper:zookeeper:jar:${zookeeper.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} diff --git a/distro/src/main/assembly/plugin-solr.xml b/distro/src/main/assembly/plugin-solr.xml index 3203831d1c8..00114a999a1 100644 --- a/distro/src/main/assembly/plugin-solr.xml +++ b/distro/src/main/assembly/plugin-solr.xml @@ -57,13 +57,9 @@ com.fasterxml.jackson.core:jackson-annotations:jar:${fasterxml.jackson.version} com.fasterxml.jackson.core:jackson-core:jar:${fasterxml.jackson.version} com.fasterxml.jackson.core:jackson-databind:jar:${fasterxml.jackson.version} - com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:${fasterxml.jackson.version} - com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:${fasterxml.jackson.version} - com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:${fasterxml.jackson.version} com.google.code.gson:gson commons-collections:commons-collections io.airlift:aircompressor:jar:${aircompressor.version} - jakarta.ws.rs:jakarta.ws.rs-api javax.inject:javax.inject joda-time:joda-time org.apache.hadoop.thirdparty:hadoop-shaded-guava:jar:${hadoop-shaded-guava.version} @@ -72,18 +68,22 @@ org.apache.httpcomponents:httpasyncclient:jar:${httpcomponents.httpasyncclient.version} org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.lucene:lucene-core - org.glassfish.hk2.external:jakarta.inject - org.glassfish.hk2:class-model - org.glassfish.hk2:hk2-api - org.glassfish.hk2:hk2-core - org.glassfish.hk2:hk2-locator - org.glassfish.hk2:hk2-runlevel - org.glassfish.hk2:hk2-utils - org.glassfish.hk2:hk2 - org.glassfish.jersey.core:jersey-common - org.glassfish.jersey.ext:jersey-entity-filtering - org.glassfish.jersey.inject:jersey-hk2 + org.apache.lucene:lucene-sandbox + + + org.glassfish.jersey.core:* + org.glassfish.jersey.ext:* + org.glassfish.jersey.inject:* + org.glassfish.jersey.media:* + org.glassfish.jersey.containers:* + org.glassfish.hk2:* + org.glassfish.hk2.external:* + com.fasterxml.jackson.jaxrs:* + com.fasterxml.jackson.module:jackson-module-jaxb-annotations:* + javax.ws.rs:javax.ws.rs-api:* + jakarta.ws.rs:jakarta.ws.rs-api:* + diff --git a/distro/src/main/assembly/plugin-sqoop.xml b/distro/src/main/assembly/plugin-sqoop.xml index 7ec87abc891..cbd4aaa551c 100644 --- a/distro/src/main/assembly/plugin-sqoop.xml +++ b/distro/src/main/assembly/plugin-sqoop.xml @@ -70,6 +70,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.hk2.external:jakarta.inject diff --git a/distro/src/main/assembly/plugin-trino.xml b/distro/src/main/assembly/plugin-trino.xml index 895b4085203..b3be12b583a 100644 --- a/distro/src/main/assembly/plugin-trino.xml +++ b/distro/src/main/assembly/plugin-trino.xml @@ -82,6 +82,7 @@ org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} org.apache.ranger:ranger-plugins-cred + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.apache.zookeeper:zookeeper:jar:${zookeeper.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} diff --git a/distro/src/main/assembly/plugin-yarn.xml b/distro/src/main/assembly/plugin-yarn.xml index 102e5703121..08d9d00f169 100644 --- a/distro/src/main/assembly/plugin-yarn.xml +++ b/distro/src/main/assembly/plugin-yarn.xml @@ -76,6 +76,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.jersey.core:jersey-client diff --git a/distro/src/main/assembly/storm-agent.xml b/distro/src/main/assembly/storm-agent.xml index 4c58db7f797..dd376f10544 100644 --- a/distro/src/main/assembly/storm-agent.xml +++ b/distro/src/main/assembly/storm-agent.xml @@ -89,6 +89,7 @@ org.apache.httpcomponents:httpcore-nio:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpcore:jar:${httpcomponents.httpcore.version} org.apache.httpcomponents:httpmime:jar:${httpcomponents.httpmime.version} + org.apache.solr:solr-api:jar:${solr.version} org.apache.solr:solr-solrj:jar:${solr.version} org.eclipse.jetty:jetty-client:jar:${jetty-client.version} org.glassfish.hk2.external:jakarta.inject diff --git a/embeddedwebserver/src/main/java/org/apache/ranger/server/tomcat/SolrCollectionBootstrapper.java b/embeddedwebserver/src/main/java/org/apache/ranger/server/tomcat/SolrCollectionBootstrapper.java index c792d842a53..6f05df5be37 100644 --- a/embeddedwebserver/src/main/java/org/apache/ranger/server/tomcat/SolrCollectionBootstrapper.java +++ b/embeddedwebserver/src/main/java/org/apache/ranger/server/tomcat/SolrCollectionBootstrapper.java @@ -18,13 +18,8 @@ */ package org.apache.ranger.server.tomcat; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.SecureClientLogin; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.util.EntityUtils; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; @@ -32,29 +27,20 @@ import org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder; import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder; import org.apache.solr.client.solrj.request.CollectionAdminRequest; +import org.apache.solr.client.solrj.request.ConfigSetAdminRequest; import org.apache.solr.client.solrj.response.CollectionAdminResponse; +import org.apache.solr.client.solrj.response.ConfigSetAdminResponse; import org.apache.solr.common.SolrException; -import org.apache.solr.common.cloud.SolrZkClient; -import org.apache.solr.common.cloud.SolrZooKeeper; -import org.apache.solr.common.cloud.ZkConfigManager; -import org.noggit.JSONParser; -import org.noggit.ObjectBuilder; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.StringReader; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -80,12 +66,10 @@ public class SolrCollectionBootstrapper extends Thread { private static final String AUTHENTICATION_TYPE = "hadoop.security.authentication"; private static final String RANGER_SERVICE_HOSTNAME = "ranger.service.host"; private static final String ADMIN_USER_PRINCIPAL = "ranger.admin.kerberos.principal"; - private static final String SSL_ENABLED_PARAM = "ranger.service.https.attrib.ssl.enabled"; - private static final int TRY_UNTIL_SUCCESS = -1; + private static final int TRY_UNTIL_SUCCESS = -1; - private final String customConfigSetLocation; - private final File configSetFolder; - private final boolean isSSLEnabled; + private final String customConfigSetLocation; + private final File configSetFolder; boolean solrCloudMode; boolean isCompleted; @@ -104,8 +88,6 @@ public class SolrCollectionBootstrapper extends Thread { Long timeInterval; SolrClient solrClient; CloudSolrClient solrCloudClient; - SolrZooKeeper solrZookeeper; - SolrZkClient zkClient; public SolrCollectionBootstrapper() throws IOException { logger.info("Starting Solr Setup"); @@ -161,39 +143,6 @@ public SolrCollectionBootstrapper() throws IOException { pathForCloudMode = Paths.get(solrFileDir, "contrib", "solr_for_audit_setup", "conf"); configSetFolder = pathForCloudMode.toFile(); } - - String sslEnabledProp = EmbeddedServerUtil.getConfig(SSL_ENABLED_PARAM); - - isSSLEnabled = ("true".equalsIgnoreCase(sslEnabledProp)); - } - - public static Map postDataAndGetResponse(CloudSolrClient cloudClient, String uri, ByteBuffer bytarr) throws IOException { - HttpPost httpPost = null; - HttpEntity entity; - String response = null; - Map m = null; - - try { - httpPost = new HttpPost(uri); - - httpPost.setHeader("Content-Type", "application/octet-stream"); - httpPost.setEntity(new ByteArrayEntity(bytarr.array(), bytarr.arrayOffset(), bytarr.limit())); - - entity = cloudClient.getLbClient().getHttpClient().execute(httpPost).getEntity(); - - try { - response = EntityUtils.toString(entity, StandardCharsets.UTF_8); - m = (Map) ObjectBuilder.getVal(new JSONParser(new StringReader(response))); - } catch (JSONParser.ParseException e) { - logger.severe("Error response: " + response); - } - } finally { - if (httpPost != null) { - httpPost.releaseConnection(); - } - } - - return m; } public void run() { @@ -248,7 +197,6 @@ private boolean connect(List zookeeperHosts) { solrCloudClient.setDefaultCollection(solrCollectionName); solrCloudClient.connect(); - zkClient = solrCloudClient.getZkStateReader().getZkClient(); solrClient = solrCloudClient; solrCloudMode = true; @@ -270,62 +218,47 @@ private void setHttpClientBuilderForKrb() { private boolean uploadConfiguration() { try { - if (zkClient != null) { - ZkConfigManager zkConfigManager = new ZkConfigManager(zkClient); - boolean configExists = zkConfigManager.configExists(solrConfigName); + if (solrCloudClient == null) { + logger.severe("Solr is in cloud mode but CloudSolrClient is not connected."); - if (!configExists) { - try { - logger.info("Config does not exist with name " + solrConfigName); + return false; + } - String zipOfConfigs = null; + ConfigSetAdminRequest.List listRequest = new ConfigSetAdminRequest.List(); + ConfigSetAdminResponse.List listResponse = listRequest.process(solrCloudClient); + List configSets = listResponse.getConfigSets(); - if (this.configSetFolder.exists() && this.configSetFolder.isFile()) { - zipOfConfigs = this.configSetFolder.getAbsolutePath(); - } else { - String[] files = this.configSetFolder.list(); - - if (files != null) { - for (String aFile : files) { - if (aFile != null) { - if (aFile.equals("solr_audit_conf.zip")) { - zipOfConfigs = this.configSetFolder + "/" + aFile; - break; - } - } - } - } - } + if (configSets != null && configSets.contains(solrConfigName)) { + logger.info("Config already exists with name " + solrConfigName); - if (zipOfConfigs == null) { - throw new FileNotFoundException("Could Not Find Configs Zip File : " + getConfigSetFolder()); - } + return true; + } - File file = new File(zipOfConfigs); - byte[] arrByte = Files.readAllBytes(file.toPath()); - ByteBuffer byteBuffer = ByteBuffer.wrap(arrByte); - String baseUrl = getBaseUrl(); - String protocol = isSSLEnabled ? "https" : "http"; - String uploadConfigsUrl = String.format("%s://%s/admin/configs?action=UPLOAD&name=%s", protocol, baseUrl, solrConfigName); + logger.info("Config does not exist with name " + solrConfigName); - postDataAndGetResponse(solrCloudClient, uploadConfigsUrl, byteBuffer); + String zipOfConfigs = resolveConfigZipPath(); - return true; - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error while uploading configs : ", ex); + if (zipOfConfigs == null) { + throw new FileNotFoundException("Could Not Find Configs Zip File : " + getConfigSetFolder()); + } - return false; - } - } else { - logger.info("Config already exists with name " + solrConfigName); + File configZip = new File(zipOfConfigs); - return true; - } - } else { - logger.severe("Solr is in cloud mode and could not find the zookeeper client for performing upload operations. "); + ConfigSetAdminRequest.Upload uploadRequest = new ConfigSetAdminRequest.Upload(); + + uploadRequest.setConfigSetName(solrConfigName); + uploadRequest.setUploadFile(configZip, "application/zip"); + uploadRequest.setOverwrite(true); + + ConfigSetAdminResponse uploadResponse = uploadRequest.process(solrCloudClient); + + if (uploadResponse.getStatus() != 0) { + logger.log(Level.SEVERE, "Error while uploading configs, response=" + uploadResponse); return false; } + + return true; } catch (Exception ex) { logger.severe("Error while uploading configuration : " + ex); @@ -333,6 +266,24 @@ private boolean uploadConfiguration() { } } + private String resolveConfigZipPath() { + if (this.configSetFolder.exists() && this.configSetFolder.isFile()) { + return this.configSetFolder.getAbsolutePath(); + } + + String[] files = this.configSetFolder.list(); + + if (files != null) { + for (String aFile : files) { + if ("solr_audit_conf.zip".equals(aFile)) { + return this.configSetFolder + "/" + aFile; + } + } + } + + return null; + } + private void logErrorMessageAndWait(String msg, Exception exception) { retryCounter++; @@ -372,9 +323,10 @@ private boolean createCollection() { logger.info("No. of shards provided is : " + noOfShards); - CollectionAdminRequest.Create createCollection = CollectionAdminRequest.createCollection(solrCollectionName, solrConfigName, noOfShards, noOfReplicas); + CollectionAdminRequest.Create createCollection = CollectionAdminRequest.createCollection( + solrCollectionName, solrConfigName, noOfShards, noOfReplicas); - createCollection.setMaxShardsPerNode(maxNodePerShards); + createCollection.withProperty("maxShardsPerNode", String.valueOf(maxNodePerShards)); CollectionAdminResponse createResponse = createCollection.process(solrClient); @@ -453,17 +405,4 @@ private static List getZkHosts() { return zookeeperHosts; } - - private String getBaseUrl() throws Exception { - Set nodes = solrCloudClient.getClusterStateProvider().getLiveNodes(); - - if (CollectionUtils.isEmpty(nodes)) { - throw new Exception("No live SolrServers available"); - } - - String[] nodeArr = nodes.toArray(new String[0]); - - // getting nodes URL as 'port_solr', so converting it to 'port/solr' - return nodeArr[0].replaceAll("_", "/"); - } } diff --git a/plugin-solr/conf/ranger-solr-security-changes.cfg b/plugin-solr/conf/ranger-solr-security-changes.cfg index a217f4f1dee..eaa84a6f022 100644 --- a/plugin-solr/conf/ranger-solr-security-changes.cfg +++ b/plugin-solr/conf/ranger-solr-security-changes.cfg @@ -16,16 +16,18 @@ # Change the original policy parameter to work with policy manager based. # # -ranger.plugin.solr.service.name %REPOSITORY_NAME% mod create-if-not-exists +ranger.plugin.solr.service.name %REPOSITORY_NAME% mod ranger.plugin.solr.policy.source.impl org.apache.ranger.admin.client.RangerAdminRESTClient mod create-if-not-exists -ranger.plugin.solr.policy.rest.url %POLICY_MGR_URL% mod create-if-not-exists +ranger.plugin.solr.policy.rest.url %POLICY_MGR_URL% mod ranger.plugin.solr.policy.rest.ssl.config.file %COMPONENT_INSTALL_DIR_NAME%/resources/ranger-policymgr-ssl.xml mod create-if-not-exists ranger.plugin.solr.policy.pollIntervalMs 30000 mod create-if-not-exists -ranger.plugin.solr.policy.cache.dir %POLICY_CACHE_FILE_PATH% mod create-if-not-exists +ranger.plugin.solr.policy.cache.dir %POLICY_CACHE_FILE_PATH% mod ranger.plugin.solr.policy.rest.client.connection.timeoutMs 120000 mod create-if-not-exists ranger.plugin.solr.policy.rest.client.read.timeoutMs 30000 mod create-if-not-exists -ranger.plugin.solr.ugi.initialize %UGI_INITIALIZE% mod create-if-not-exists -ranger.plugin.solr.ugi.login.type %UGI_LOGIN_TYPE% mod create-if-not-exists -ranger.plugin.solr.ugi.jaas.appconfig %UGI_JAAS_APPCONFIG% mod create-if-not-exists +ranger.plugin.solr.ugi.initialize %UGI_INITIALIZE% mod create-if-not-exists +ranger.plugin.solr.ugi.login.type %UGI_LOGIN_TYPE% mod create-if-not-exists +ranger.plugin.solr.ugi.jaas.appconfig %UGI_JAAS_APPCONFIG% mod create-if-not-exists +ranger.plugin.solr.ugi.keytab.principal %UGI_KEYTAB_PRINCIPAL% mod create-if-not-exists +ranger.plugin.solr.ugi.keytab.file %UGI_KEYTAB_FILE% mod create-if-not-exists diff --git a/plugin-solr/pom.xml b/plugin-solr/pom.xml index b0562056000..cefeff35fa3 100644 --- a/plugin-solr/pom.xml +++ b/plugin-solr/pom.xml @@ -31,37 +31,16 @@ UTF-8 - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-base - ${fasterxml.jackson.version} - - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider - ${fasterxml.jackson.version} - - - jakarta.activation - jakarta.activation-api - - - - - com.fasterxml.jackson.module - jackson-module-jaxb-annotations - ${fasterxml.jackson.version} - - - jakarta.ws.rs - jakarta.ws.rs-api - ${jakarta.ws.rs-api.version} - org.apache.commons commons-text ${commons.text.version} + + org.apache.lucene + lucene-sandbox + ${solr.lucene.version} + org.apache.ranger credentialbuilder @@ -71,16 +50,83 @@ org.apache.ranger ranger-audit-dest-hdfs ${project.version} + + + org.glassfish.jersey.core + jersey-client + + + org.glassfish.jersey.core + jersey-common + + + org.glassfish.jersey.ext + jersey-entity-filtering + + + org.glassfish.jersey.inject + jersey-hk2 + + + org.glassfish.jersey.media + jersey-media-json-jackson + + org.apache.ranger ranger-audit-dest-solr ${project.version} + + + org.glassfish.jersey.core + jersey-client + + + org.glassfish.jersey.core + jersey-common + + + org.glassfish.jersey.ext + jersey-entity-filtering + + + org.glassfish.jersey.inject + jersey-hk2 + + + org.glassfish.jersey.media + jersey-media-json-jackson + + org.apache.ranger ranger-plugins-common ${project.version} + + + + org.glassfish.jersey.core + jersey-client + + + org.glassfish.jersey.core + jersey-common + + + org.glassfish.jersey.ext + jersey-entity-filtering + + + org.glassfish.jersey.inject + jersey-hk2 + + + org.glassfish.jersey.media + jersey-media-json-jackson + + org.apache.solr @@ -146,87 +192,46 @@ - javax.inject - javax.inject - ${javax.inject.version} - runtime - - - org.glassfish.hk2 - class-model - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2 - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2-api - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2-core - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2-locator - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2-runlevel - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2 - hk2-utils - ${glassfish.hk2.version} - runtime - - - org.glassfish.hk2.external - jakarta.inject - ${glassfish.hk2.version} - runtime + javax.ws.rs + javax.ws.rs-api + ${javax.ws.rs-api.version} + provided + org.glassfish.jersey.core jersey-client - ${jersey-client.version} - runtime + ${solr.jersey.version} + provided org.glassfish.jersey.core jersey-common - ${jersey-client.version} - runtime + ${solr.jersey.version} + provided org.glassfish.jersey.ext jersey-entity-filtering - ${jersey-client.version} - runtime + ${solr.jersey.version} + provided org.glassfish.jersey.inject jersey-hk2 - ${jersey-client.version} - runtime + ${solr.jersey.version} + provided org.glassfish.jersey.media jersey-media-json-jackson - ${jersey-client.version} + ${solr.jersey.version} + provided + + + javax.inject + javax.inject + ${javax.inject.version} runtime diff --git a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java index 2206efedcb6..38cbb8acb17 100644 --- a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java +++ b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java @@ -232,18 +232,33 @@ public AuthorizationResponse authorize(AuthorizationContext context) { } break; } - case METRICS_HISTORY_READ_PERM: - case METRICS_READ_PERM: { + case METRICS_READ_PERM: + case HEALTH_PERM: { rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.METRICS, RangerSolrConstants.AccessType.QUERY)); break; } - case AUTOSCALING_READ_PERM: - case AUTOSCALING_HISTORY_READ_PERM: { - rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.AUTOSCALING, RangerSolrConstants.AccessType.QUERY)); + case ZK_READ_PERM: { + rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.SECURITY, RangerSolrConstants.AccessType.QUERY)); + break; + } + case FILESTORE_READ_PERM: { + rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.METRICS, RangerSolrConstants.AccessType.QUERY)); + break; + } + case FILESTORE_WRITE_PERM: { + rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.METRICS, RangerSolrConstants.AccessType.UPDATE)); + break; + } + case PACKAGE_READ_PERM: { + for (String s : SolrAuthzUtil.getConfigAuthorizables(context)) { + rangerRequests.add(createRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.ResourceType.CONFIG, s, RangerSolrConstants.AccessType.QUERY)); + } break; } - case AUTOSCALING_WRITE_PERM: { - rangerRequests.add(createAdminRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.AdminType.AUTOSCALING, RangerSolrConstants.AccessType.UPDATE)); + case PACKAGE_EDIT_PERM: { + for (String s : SolrAuthzUtil.getConfigAuthorizables(context)) { + rangerRequests.add(createRequest(userName, userGroups, ip, eventTime, RangerSolrConstants.ResourceType.CONFIG, s, RangerSolrConstants.AccessType.UPDATE)); + } break; } case ALL: { diff --git a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SolrAuthzUtil.java b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SolrAuthzUtil.java index 52d06711059..e9dd5dee5f0 100644 --- a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SolrAuthzUtil.java +++ b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SolrAuthzUtil.java @@ -153,7 +153,6 @@ static Map getCollectionsForAdminOp(Auth case SYNCSHARD: case MOVEREPLICA: case RESTORE: - case MIGRATESTATEFORMAT: case FORCELEADER: case REBALANCELEADERS: case BALANCESHARDUNIQUE: @@ -210,8 +209,6 @@ static Map getCoresForAdminOp(Authorizat case REQUESTSTATUS: case OVERSEEROP: - case INVOKE: - // TODO - is this correct ? case DELETEALIAS: { return Collections.emptyMap(); } diff --git a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SubsetQueryPlugin.java b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SubsetQueryPlugin.java index 011908cc4c2..eb3d5b5a8cb 100644 --- a/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SubsetQueryPlugin.java +++ b/plugin-solr/src/main/java/org/apache/ranger/authorization/solr/authorizer/SubsetQueryPlugin.java @@ -21,9 +21,9 @@ import org.apache.hadoop.thirdparty.com.google.common.base.Preconditions; import org.apache.lucene.index.Term; +import org.apache.lucene.sandbox.search.CoveringQuery; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.CoveringQuery; import org.apache.lucene.search.LongValuesSource; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; diff --git a/pom.xml b/pom.xml index 234c52a9f9b..44bb6994d21 100755 --- a/pom.xml +++ b/pom.xml @@ -211,7 +211,9 @@ 2.5 2.0.13 2.0.13 - 8.11.3 + 2.39.1 + 9.8.0 + 9.4.1 reuseReports jacoco java @@ -1126,12 +1128,15 @@ agents-common agents-cred agents-installer + authz-api common-utils credentialbuilder + distro plugin-solr ranger-plugin-classloader ranger-solr-plugin-shim ranger-util + ugsync-util diff --git a/ranger-solr-plugin-shim/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java b/ranger-solr-plugin-shim/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java index 832717b7313..b3fc6450c03 100644 --- a/ranger-solr-plugin-shim/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java +++ b/ranger-solr-plugin-shim/src/main/java/org/apache/ranger/authorization/solr/authorizer/RangerSolrAuthorizer.java @@ -20,7 +20,6 @@ import org.apache.ranger.plugin.classloader.PluginClassLoaderActivator; import org.apache.ranger.plugin.classloader.RangerPluginClassLoader; -import org.apache.solr.common.StringUtils; import org.apache.solr.common.util.NamedList; import org.apache.solr.handler.component.ResponseBuilder; import org.apache.solr.handler.component.SearchComponent; @@ -32,6 +31,7 @@ import java.io.IOException; import java.util.Map; +import java.util.Objects; public class RangerSolrAuthorizer extends SearchComponent implements AuthorizationPlugin { private static final Logger LOG = LoggerFactory.getLogger(RangerSolrAuthorizer.class); @@ -56,7 +56,7 @@ public void close() throws IOException { LOG.debug("==> RangerSolrAuthorizer.close(Resource)"); // close() to be forwarded only for authorizer instance - boolean isAuthorizer = StringUtils.equals(super.getName(), RANGER_SOLR_AUTHORIZER_IMPL_CLASSNAME); + boolean isAuthorizer = Objects.equals(super.getName(), RANGER_SOLR_AUTHORIZER_IMPL_CLASSNAME); if (isAuthorizer) { try (PluginClassLoaderActivator ignored = new PluginClassLoaderActivator(pluginClassLoader, "close")) { diff --git a/security-admin/pom.xml b/security-admin/pom.xml index 491baf80fcb..08d5e7fd715 100644 --- a/security-admin/pom.xml +++ b/security-admin/pom.xml @@ -545,6 +545,11 @@ unixauthclient ${project.version} + + org.apache.solr + solr-api + ${solr.version} + org.apache.solr solr-solrj @@ -582,6 +587,31 @@ io.netty netty-transport-native-unix-common + + + org.apache.lucene + lucene-analysis-common + + + org.apache.lucene + lucene-backward-codecs + + + org.apache.lucene + lucene-core + + + org.apache.lucene + lucene-queries + + + org.apache.lucene + lucene-queryparser + + + org.apache.lucene + lucene-sandbox + org.apache.zookeeper zookeeper-jute