From 10727eff669c05281cc4679db37e96bfe99e2f7b Mon Sep 17 00:00:00 2001 From: liangfuxia Date: Fri, 22 Nov 2019 11:40:18 +0800 Subject: [PATCH 1/6] update dataimport --- .../solr/handler/dataimport/AESCipher.java | 100 ++++++++++++++++++ .../solr/handler/dataimport/DocBuilder.java | 20 ++++ .../handler/dataimport/JdbcDataSource.java | 58 ++++++++-- .../dataimport/SilkcloudIndexDocument.java | 38 +++++++ 4 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java create mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SilkcloudIndexDocument.java diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java new file mode 100644 index 000000000000..1f666b56a030 --- /dev/null +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java @@ -0,0 +1,100 @@ +// +// Decompiled by Procyon v0.5.36 +// + +package org.apache.solr.handler.dataimport; + +import org.slf4j.LoggerFactory; +import org.apache.commons.codec.DecoderException; +import javax.crypto.spec.SecretKeySpec; +import org.apache.solr.common.StringUtils; +import org.apache.commons.codec.binary.Hex; +import java.security.spec.AlgorithmParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.Cipher; +import org.slf4j.Logger; +import java.security.Key; +import java.security.SecureRandom; + +public class AESCipher +{ + private SecureRandom rand; + private static final Integer IV_LENGTH; + private static final String IV_SEPARATOR = "#"; + private Key key; + private static final Logger LOGGER; + private static final byte[] DEFAULT_IV; + private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; + + public AESCipher(final String keyStr) { + this.rand = new SecureRandom(); + this.key = this.stringToKey(keyStr); + } + + public String encrypt(final String message) { + if (message == null) { + throw new IllegalArgumentException("message is null"); + } + if (this.key == null) { + throw new IllegalStateException("key is null"); + } + try { + final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + final byte[] iv = this.generateIV(AESCipher.IV_LENGTH); + final IvParameterSpec ivspec = new IvParameterSpec(iv); + cipher.init(1, this.key, ivspec); + return new String(Hex.encodeHex(iv)) + "#" + new String(Hex.encodeHex(cipher.doFinal(message.getBytes("UTF-8")))); + } + catch (Exception e) { + throw new RuntimeException("Encrypt exception: ", e); + } + } + + public String decrypt(final String encryptedMessage) { + if (encryptedMessage == null) { + throw new IllegalArgumentException("encryptedMessage is null"); + } + if (this.key == null) { + throw new IllegalStateException("key is null"); + } + try { + final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + String[] info = encryptedMessage.split("#"); + if (info.length != 2) { + info = new String[] { new String(Hex.encodeHex(AESCipher.DEFAULT_IV)), encryptedMessage }; + } + final IvParameterSpec ivspec = new IvParameterSpec(Hex.decodeHex(info[0].toCharArray())); + cipher.init(2, this.key, ivspec); + return new String(cipher.doFinal(Hex.decodeHex(info[1].toCharArray())), "UTF-8"); + } + catch (Exception e) { + throw new RuntimeException("Decrypt exception : ", e); + } + } + + public Key stringToKey(final String keyStr) { + if (StringUtils.isEmpty(keyStr)) { + AESCipher.LOGGER.error("keyStr is empty."); + throw new RuntimeException("keyStr is empty."); + } + try { + final byte[] bytes = Hex.decodeHex(keyStr.toCharArray()); + return new SecretKeySpec(bytes, 0, bytes.length, "AES"); + } + catch (DecoderException decodeException) { + throw new RuntimeException("Key String to AES key: ", (Throwable)decodeException); + } + } + + private byte[] generateIV(final int length) { + final byte[] bytes = new byte[length]; + this.rand.nextBytes(bytes); + return bytes; + } + + static { + IV_LENGTH = 16; + LOGGER = LoggerFactory.getLogger((Class)AESCipher.class); + DEFAULT_IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + } +} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DocBuilder.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DocBuilder.java index 164cf7025126..3019d58a394e 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DocBuilder.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DocBuilder.java @@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import com.fasterxml.jackson.databind.ObjectMapper; /** *

{@link DocBuilder} is responsible for creating Solr documents out of the given configuration. It also maintains @@ -83,6 +84,7 @@ public class DocBuilder { private DIHProperties propWriter; private DebugLogger debugLogger; private final RequestInfo reqParams; + private ObjectMapper mapper; public DocBuilder(DataImporter dataImporter, DIHWriter solrWriter, DIHProperties propWriter, RequestInfo reqParams) { INSTANCE.set(this); @@ -98,6 +100,7 @@ public DocBuilder(DataImporter dataImporter, DIHWriter solrWriter, DIHProperties if (writer != null) { writer.init(ctx); } + this.mapper = new ObjectMapper(); } @@ -650,6 +653,23 @@ private void addFields(Entity entity, DocWrapper doc, Object value = entry.getValue(); if (value == null) continue; if (key.startsWith("$")) continue; + if (key.equalsIgnoreCase("payload")) { + if (value == null) { + continue; + } + try { + final SilkcloudIndexDocument document = (SilkcloudIndexDocument)mapper.readValue(value.toString(), (Class)SilkcloudIndexDocument.class); + for (final Map.Entry fieldEntry : document.getFields().entrySet()) { + if (fieldEntry.getValue() != null) { + doc.addField((String)fieldEntry.getKey(), fieldEntry.getValue()); + } + } + continue; + } + catch (Exception e) { + throw new DataImportHandlerException(500, e); + } + } Set field = entity.getColNameVsField().get(key); IndexSchema schema = null == reqParams.getRequest() ? null : reqParams.getRequest().getSchema(); if (field == null && schema != null) { diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java index a8eed55f739d..fd67a1a9ebf2 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java @@ -16,10 +16,6 @@ */ package org.apache.solr.handler.dataimport; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.solr.handler.dataimport.DataImportHandlerException.wrapAndThrow; -import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE; - import org.apache.solr.common.SolrException; import org.apache.solr.util.CryptoKeys; import org.slf4j.Logger; @@ -27,7 +23,6 @@ import javax.naming.InitialContext; import javax.naming.NamingException; - import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; @@ -39,6 +34,31 @@ import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import java.math.BigInteger; +import java.math.BigDecimal; +import java.sql.Statement; +import java.sql.ResultSet; +import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; +import java.sql.ResultSetMetaData; +import javax.naming.NamingException; +import javax.naming.InitialContext; +import java.util.concurrent.TimeUnit; +import java.sql.SQLException; +import java.sql.Driver; +import java.sql.DriverManager; +import java.util.Properties; +import java.util.HashMap; +import java.sql.Connection; +import java.util.concurrent.Callable; +import org.slf4j.Logger; +import java.util.Map; +import java.util.Iterator; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE; +import static org.apache.solr.handler.dataimport.DataImportHandlerException.wrapAndThrow; /** *

A DataSource implementation which can fetch data using JDBC.

Refer to entry : initProps.entrySet()) { - if (entry.getValue() != null) { - entry.setValue(ctx.replaceTokens((String) entry.getValue())); + final Map encryptedMap = new HashMap(); + for (final Map.Entry entry : initProps.entrySet()) { + if (entry.getValue() != null) { + final String value = ctx.replaceTokens((String)entry.getValue()); + if (entry.getKey().toString().endsWith(".encrypted")) { + String cipherKey = System.getProperty("cipherkey"); + if (cipherKey == null || cipherKey.length() == 0) { + cipherKey = System.getenv("CIPHER_KEY"); + } + if (cipherKey == null || cipherKey.length() == 0) { + throw new RuntimeException("Cipher key not found"); + } + final AESCipher aesCipher = new AESCipher(cipherKey); + final String key = entry.getKey().toString(); + encryptedMap.put(key.substring(0, key.lastIndexOf(".")), aesCipher.decrypt(value)); + } + else { + entry.setValue(value); + } + } } - } + for (final Object key2 : encryptedMap.keySet()) { + initProps.remove(key2 + ".encrypted"); + } + initProps.putAll(encryptedMap); } @Override diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SilkcloudIndexDocument.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SilkcloudIndexDocument.java new file mode 100644 index 000000000000..5674c5c0ccfa --- /dev/null +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SilkcloudIndexDocument.java @@ -0,0 +1,38 @@ +// +// Decompiled by Procyon v0.5.36 +// + +package org.apache.solr.handler.dataimport; + +import com.fasterxml.jackson.annotation.JsonCreator; +import java.io.IOException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; + +public class SilkcloudIndexDocument +{ + private Map fields; + + public SilkcloudIndexDocument() { + this.fields = new HashMap(); + } + + public Map getFields() { + return this.fields; + } + + public void setFields(final Map fields) { + this.fields = fields; + } + + @JsonCreator + public static SilkcloudIndexDocument create(final String jsonString) throws JsonParseException, JsonMappingException, IOException { + final ObjectMapper mapper = new ObjectMapper(); + SilkcloudIndexDocument doc = null; + doc = (SilkcloudIndexDocument)mapper.readValue(jsonString, (Class)SilkcloudIndexDocument.class); + return doc; + } +} From 36a3f008bd18fb1611a110d9fe24740d4f76b60a Mon Sep 17 00:00:00 2001 From: liangfuxia Date: Fri, 12 Nov 2021 18:45:29 +0800 Subject: [PATCH 2/6] add vault service --- lucene/expressions/ivy.xml | 3 + lucene/ivy-versions.properties | 8 ++ .../solr/handler/dataimport/AESCipher.java | 100 ------------------ .../handler/dataimport/JdbcDataSource.java | 17 ++- .../handler/dataimport/VaultServiceImpl.java | 61 +++++++++++ solr/core/ivy.xml | 4 + 6 files changed, 82 insertions(+), 111 deletions(-) delete mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java create mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java diff --git a/lucene/expressions/ivy.xml b/lucene/expressions/ivy.xml index 6065522962f6..58cc5392fe39 100644 --- a/lucene/expressions/ivy.xml +++ b/lucene/expressions/ivy.xml @@ -25,6 +25,9 @@ + + + diff --git a/lucene/ivy-versions.properties b/lucene/ivy-versions.properties index 4d3b6c0caac4..ccd5cfa7b1a9 100644 --- a/lucene/ivy-versions.properties +++ b/lucene/ivy-versions.properties @@ -128,6 +128,7 @@ org.apache.calcite.version = 1.18.0 /org.apache.commons/commons-collections4 = 4.2 /org.apache.commons/commons-compress = 1.18 /org.apache.commons/commons-configuration2 = 2.1.1 +/commons-configuration/commons-configuration = 1.10 /org.apache.commons/commons-exec = 1.3 /org.apache.commons/commons-lang3 = 3.8.1 /org.apache.commons/commons-math3 = 3.6.1 @@ -325,3 +326,10 @@ ua.net.nlp.morfologik-ukrainian-search.version = 3.9.0 /ua.net.nlp/morfologik-ukrainian-search = ${ua.net.nlp.morfologik-ukrainian-search.version} /xerces/xercesImpl = 2.9.1 + +org.springframework.vault.version =2.3.2 +/org.springframework.vault/spring-vault-core = ${org.springframework.vault.version} + +org.springframework.spring.version = 5.0.12.RELEASE +/org.springframework/spring-beans = ${org.springframework.spring.version} +/org.springframework/spring-web = ${org.springframework.spring.version} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java deleted file mode 100644 index 1f666b56a030..000000000000 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/AESCipher.java +++ /dev/null @@ -1,100 +0,0 @@ -// -// Decompiled by Procyon v0.5.36 -// - -package org.apache.solr.handler.dataimport; - -import org.slf4j.LoggerFactory; -import org.apache.commons.codec.DecoderException; -import javax.crypto.spec.SecretKeySpec; -import org.apache.solr.common.StringUtils; -import org.apache.commons.codec.binary.Hex; -import java.security.spec.AlgorithmParameterSpec; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.Cipher; -import org.slf4j.Logger; -import java.security.Key; -import java.security.SecureRandom; - -public class AESCipher -{ - private SecureRandom rand; - private static final Integer IV_LENGTH; - private static final String IV_SEPARATOR = "#"; - private Key key; - private static final Logger LOGGER; - private static final byte[] DEFAULT_IV; - private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; - - public AESCipher(final String keyStr) { - this.rand = new SecureRandom(); - this.key = this.stringToKey(keyStr); - } - - public String encrypt(final String message) { - if (message == null) { - throw new IllegalArgumentException("message is null"); - } - if (this.key == null) { - throw new IllegalStateException("key is null"); - } - try { - final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - final byte[] iv = this.generateIV(AESCipher.IV_LENGTH); - final IvParameterSpec ivspec = new IvParameterSpec(iv); - cipher.init(1, this.key, ivspec); - return new String(Hex.encodeHex(iv)) + "#" + new String(Hex.encodeHex(cipher.doFinal(message.getBytes("UTF-8")))); - } - catch (Exception e) { - throw new RuntimeException("Encrypt exception: ", e); - } - } - - public String decrypt(final String encryptedMessage) { - if (encryptedMessage == null) { - throw new IllegalArgumentException("encryptedMessage is null"); - } - if (this.key == null) { - throw new IllegalStateException("key is null"); - } - try { - final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - String[] info = encryptedMessage.split("#"); - if (info.length != 2) { - info = new String[] { new String(Hex.encodeHex(AESCipher.DEFAULT_IV)), encryptedMessage }; - } - final IvParameterSpec ivspec = new IvParameterSpec(Hex.decodeHex(info[0].toCharArray())); - cipher.init(2, this.key, ivspec); - return new String(cipher.doFinal(Hex.decodeHex(info[1].toCharArray())), "UTF-8"); - } - catch (Exception e) { - throw new RuntimeException("Decrypt exception : ", e); - } - } - - public Key stringToKey(final String keyStr) { - if (StringUtils.isEmpty(keyStr)) { - AESCipher.LOGGER.error("keyStr is empty."); - throw new RuntimeException("keyStr is empty."); - } - try { - final byte[] bytes = Hex.decodeHex(keyStr.toCharArray()); - return new SecretKeySpec(bytes, 0, bytes.length, "AES"); - } - catch (DecoderException decodeException) { - throw new RuntimeException("Key String to AES key: ", (Throwable)decodeException); - } - } - - private byte[] generateIV(final int length) { - final byte[] bytes = new byte[length]; - this.rand.nextBytes(bytes); - return bytes; - } - - static { - IV_LENGTH = 16; - LOGGER = LoggerFactory.getLogger((Class)AESCipher.class); - DEFAULT_IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - } -} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java index fd67a1a9ebf2..94b6b5187990 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java @@ -55,6 +55,7 @@ import org.slf4j.Logger; import java.util.Map; import java.util.Iterator; +import org.apache.solr.handler.dataimport.VaultServiceImpl; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE; @@ -288,20 +289,14 @@ private Connection getFromJndi(final Properties initProps, final String jndiName private void resolveVariables(Context ctx, Properties initProps) { final Map encryptedMap = new HashMap(); + VaultServiceImpl vaultService = new VaultServiceImpl(); + Properties properties = vaultService.readVaultProperties(); for (final Map.Entry entry : initProps.entrySet()) { if (entry.getValue() != null) { final String value = ctx.replaceTokens((String)entry.getValue()); - if (entry.getKey().toString().endsWith(".encrypted")) { - String cipherKey = System.getProperty("cipherkey"); - if (cipherKey == null || cipherKey.length() == 0) { - cipherKey = System.getenv("CIPHER_KEY"); - } - if (cipherKey == null || cipherKey.length() == 0) { - throw new RuntimeException("Cipher key not found"); - } - final AESCipher aesCipher = new AESCipher(cipherKey); + if (entry.getKey().toString().endsWith(".vaultPath")) { final String key = entry.getKey().toString(); - encryptedMap.put(key.substring(0, key.lastIndexOf(".")), aesCipher.decrypt(value)); + encryptedMap.put(key.substring(0, key.lastIndexOf(".")), properties.getProperty(value)); } else { entry.setValue(value); @@ -309,7 +304,7 @@ private void resolveVariables(Context ctx, Properties initProps) { } } for (final Object key2 : encryptedMap.keySet()) { - initProps.remove(key2 + ".encrypted"); + initProps.remove(key2 + ".vaultPath"); } initProps.putAll(encryptedMap); } diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java new file mode 100644 index 000000000000..9ee8264fcbb1 --- /dev/null +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java @@ -0,0 +1,61 @@ +package org.apache.solr.handler.dataimport; + +import org.springframework.vault.authentication.TokenAuthentication; +import org.springframework.vault.client.VaultEndpoint; +import org.springframework.vault.core.VaultTemplate; +import org.springframework.vault.support.VaultResponse; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; + +public class VaultServiceImpl { + private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; + private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; + private static final String ENV_VAULT_PATH = "VAULT_PATH"; + private static final String DATA = "data"; + + private VaultTemplate vaultTemplate; + + public VaultServiceImpl() { + try { + String vaultToken = System.getenv(ENV_VAULT_TOKEN); + String vaultHost = System.getenv(ENV_VAULT_ADDR); + vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); + } catch (Exception e) { + throw new RuntimeException("Failed to connect to vault using token", e); + } + } + + public Properties readVaultProperties() { + String vaultPath = System.getenv(ENV_VAULT_PATH); + if (vaultPath == null || vaultPath.length() == 0) { + throw new RuntimeException(ENV_VAULT_PATH + " environment parameter is missing"); + } + try { + VaultResponse vaultResponse = vaultTemplate.read(vaultPath); + return readVaultProperties(vaultResponse); + } catch (Exception e) { + // Do nothing + throw new RuntimeException("readVaultProperties error", e); + } + } + + private static Properties readVaultProperties(VaultResponse vaultResponse) { + if (vaultResponse != null && vaultResponse.getData() != null && vaultResponse.getData().get(DATA) != null) { + Object obj = vaultResponse.getData().get(DATA); + if (!(obj instanceof Map)) { + return new Properties(); + } + + Map keyPairs = (Map)vaultResponse.getData().get(DATA); + Properties properties = new Properties(); + for (Map.Entry entry : keyPairs.entrySet()) { + properties.put(entry.getKey(), entry.getValue().toString()); + } + return properties; + } + + return new Properties(); + } +} diff --git a/solr/core/ivy.xml b/solr/core/ivy.xml index 9fba66347ac4..a3abe3aaf692 100644 --- a/solr/core/ivy.xml +++ b/solr/core/ivy.xml @@ -51,6 +51,10 @@ + + + + From 70e8f1e792a560cfba709cd90e4f549a268a70f3 Mon Sep 17 00:00:00 2001 From: Puru Yanamala Date: Fri, 3 May 2024 12:25:01 +0100 Subject: [PATCH 3/6] [GENE-2434] - Vault token read from file. --- lucene/default-nested-ivy-settings.xml | 2 +- .../solr/handler/dataimport/FileWatcher.java | 184 ++++++++++++++++++ .../handler/dataimport/VaultServiceImpl.java | 39 +++- 3 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java diff --git a/lucene/default-nested-ivy-settings.xml b/lucene/default-nested-ivy-settings.xml index c9fe95be0ce3..9961a4d33c4d 100644 --- a/lucene/default-nested-ivy-settings.xml +++ b/lucene/default-nested-ivy-settings.xml @@ -33,7 +33,7 @@ - + diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java new file mode 100644 index 000000000000..c0ddec7d5acf --- /dev/null +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java @@ -0,0 +1,184 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (C) 2014 SilkCloud and/or its affiliates. All rights reserved. + */ + +package org.apache.solr.handler.dataimport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; +import static java.nio.file.StandardWatchEventKinds.*; + +/** + * Java doc. + */ +public class FileWatcher { + //region singleton + private static volatile FileWatcher instance; + + public static FileWatcher getInstance() { + // lazy singleton + if (instance == null) { + synchronized (FileWatcher.class) { + if (instance == null) { + FileWatcher instance = new FileWatcher(); + instance.initialize(); + FileWatcher.instance = instance; + } + } + } + return instance; + } + + public static void setInstance(FileWatcher watcher) { + // setInstance for unit testing + instance = watcher; + } + //endregion + + //region private fields + private static Logger logger = LoggerFactory.getLogger(FileWatcher.class); + + private Thread thread; + private WatchService watchService; + private FileChangeListenerMap listeners = new FileChangeListenerMap(); + //endregion + + /**. + * File listener + */ + public interface FileListener { + void onFileChanged(Path path, WatchEvent.Kind kind); + } + + public FileWatcher addListener(Path path, FileListener listener) { + try { + WatchKey key = path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY); + listeners.addListener(key, listener); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + + return this; + } + + public void close() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + + //region private methods + + // protected empty constructor for subclassing/mocking + protected FileWatcher() { + } + + private void initialize() { + try { + watchService = FileSystems.getDefault().newWatchService(); + } + catch (IOException ex) { + throw new RuntimeException("Error creating watch service.", ex); + } + thread = new Thread(new Runnable() { + @Override + public void run() { + FileWatcher.this.run(); + } + }); + thread.start(); + } + + private void run() { + for (; ; ) { + try { + WatchKey key = watchService.take(); + Path path = (Path) key.watchable(); + + for (WatchEvent event : key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + + if (kind == StandardWatchEventKinds.OVERFLOW) { + logger.warn("Overflow happened in FileWatcher for key " + key); + continue; + } + + WatchEvent ev = (WatchEvent) event; + listeners.notify(key, path, ev.kind()); + } + } + catch (InterruptedException ex) { + return; + } + catch (Exception ex) { + logger.warn("Error occurred in file watcher. ", ex); + } + } + } + + //endregion + + //region private classes + + private static final class FileChangeListenerList { + private ArrayList> listeners = new ArrayList<>(); + + public void addListener(FileListener listener) { + listeners.add(new WeakReference<>(listener)); + } + + public void notify(Path path, WatchEvent.Kind kind) { + ArrayList> toRemove = new ArrayList<>(); + for (WeakReference listenerWeakReference : listeners) { + FileListener listener = listenerWeakReference.get(); + if (listener == null) { + toRemove.add(listenerWeakReference); + } + else { + try { + listener.onFileChanged(path, kind); + } + catch (Exception ex) { + logger.warn("Error occurred in file watcher. ", ex); + } + } + } + listeners.removeAll(toRemove); + } + } + + private static final class FileChangeListenerMap { + private ConcurrentHashMap listeners = new ConcurrentHashMap<>(); + + public void addListener(WatchKey watchKey, FileListener listener) { + FileChangeListenerList list = listeners.get(watchKey); + if (list == null) { + final FileChangeListenerList newList = new FileChangeListenerList(); + list = listeners.putIfAbsent(watchKey, newList); + if (list == null) { + list = newList; + } + } + list.addListener(listener); + } + + public void notify(WatchKey watchKey, Path path, WatchEvent.Kind kind) { + FileChangeListenerList list = listeners.get(watchKey); + if (list != null) { + list.notify(path, kind); + } + } + } + + //endregion +} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java index 9ee8264fcbb1..2a846178bd3d 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java @@ -6,25 +6,47 @@ import org.springframework.vault.support.VaultResponse; import java.net.URI; +import java.util.List; import java.util.Map; import java.util.Properties; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.io.*; public class VaultServiceImpl { private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; + private static final String ENV_VAULT_AUTH_PATH = "VAULT_AUTH_PATH"; private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; private static final String ENV_VAULT_PATH = "VAULT_PATH"; private static final String DATA = "data"; - + private static final String vaultTokenFilePath = System.getenv().getOrDefault(ENV_VAULT_AUTH_PATH, "/etc/vault/token"); private VaultTemplate vaultTemplate; + private String vaultToken; + private String vaultHost; public VaultServiceImpl() { try { - String vaultToken = System.getenv(ENV_VAULT_TOKEN); - String vaultHost = System.getenv(ENV_VAULT_ADDR); + vaultToken = getVaultToken(); + vaultHost = System.getenv(ENV_VAULT_ADDR); vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); } catch (Exception e) { throw new RuntimeException("Failed to connect to vault using token", e); } + watchVaultFileUpdates(); + } + + private String getVaultToken() { + try { + List lines = Files.readAllLines(Paths.get(vaultTokenFilePath)); + if (!lines.isEmpty()) { + return lines.get(0); + } else { + throw new RuntimeException(vaultTokenFilePath + ": vault auth token file is empty."); + } + } catch (IOException e) { + throw new RuntimeException("Error reading vault auth token file", e); + } } public Properties readVaultProperties() { @@ -58,4 +80,15 @@ private static Properties readVaultProperties(VaultResponse vaultResponse) { return new Properties(); } + + private void watchVaultFileUpdates() { + FileWatcher.getInstance().addListener(Paths.get(vaultTokenFilePath).getParent(), (path, kind) -> { + vaultToken = getVaultToken(); + try { + vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); + } catch (Exception e) { + throw new RuntimeException("vault configuration is wrong", e); + } + }); + } } From 9bcd639e6a00a8203de8db6975010bd51e7a0ffa Mon Sep 17 00:00:00 2001 From: Puru Yanamala Date: Wed, 8 May 2024 11:01:48 +0100 Subject: [PATCH 4/6] Revert "[GENE-2434] - Vault token read from file." This reverts commit 70e8f1e792a560cfba709cd90e4f549a268a70f3. --- lucene/default-nested-ivy-settings.xml | 2 +- .../solr/handler/dataimport/FileWatcher.java | 184 ------------------ .../handler/dataimport/VaultServiceImpl.java | 39 +--- 3 files changed, 4 insertions(+), 221 deletions(-) delete mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java diff --git a/lucene/default-nested-ivy-settings.xml b/lucene/default-nested-ivy-settings.xml index 9961a4d33c4d..c9fe95be0ce3 100644 --- a/lucene/default-nested-ivy-settings.xml +++ b/lucene/default-nested-ivy-settings.xml @@ -33,7 +33,7 @@ - + diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java deleted file mode 100644 index c0ddec7d5acf..000000000000 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (C) 2014 SilkCloud and/or its affiliates. All rights reserved. - */ - -package org.apache.solr.handler.dataimport; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.nio.file.*; -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import static java.nio.file.StandardWatchEventKinds.*; - -/** - * Java doc. - */ -public class FileWatcher { - //region singleton - private static volatile FileWatcher instance; - - public static FileWatcher getInstance() { - // lazy singleton - if (instance == null) { - synchronized (FileWatcher.class) { - if (instance == null) { - FileWatcher instance = new FileWatcher(); - instance.initialize(); - FileWatcher.instance = instance; - } - } - } - return instance; - } - - public static void setInstance(FileWatcher watcher) { - // setInstance for unit testing - instance = watcher; - } - //endregion - - //region private fields - private static Logger logger = LoggerFactory.getLogger(FileWatcher.class); - - private Thread thread; - private WatchService watchService; - private FileChangeListenerMap listeners = new FileChangeListenerMap(); - //endregion - - /**. - * File listener - */ - public interface FileListener { - void onFileChanged(Path path, WatchEvent.Kind kind); - } - - public FileWatcher addListener(Path path, FileListener listener) { - try { - WatchKey key = path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY); - listeners.addListener(key, listener); - } - catch (Exception ex) { - throw new RuntimeException(ex); - } - - return this; - } - - public void close() { - if (thread != null) { - thread.interrupt(); - thread = null; - } - } - - //region private methods - - // protected empty constructor for subclassing/mocking - protected FileWatcher() { - } - - private void initialize() { - try { - watchService = FileSystems.getDefault().newWatchService(); - } - catch (IOException ex) { - throw new RuntimeException("Error creating watch service.", ex); - } - thread = new Thread(new Runnable() { - @Override - public void run() { - FileWatcher.this.run(); - } - }); - thread.start(); - } - - private void run() { - for (; ; ) { - try { - WatchKey key = watchService.take(); - Path path = (Path) key.watchable(); - - for (WatchEvent event : key.pollEvents()) { - WatchEvent.Kind kind = event.kind(); - - if (kind == StandardWatchEventKinds.OVERFLOW) { - logger.warn("Overflow happened in FileWatcher for key " + key); - continue; - } - - WatchEvent ev = (WatchEvent) event; - listeners.notify(key, path, ev.kind()); - } - } - catch (InterruptedException ex) { - return; - } - catch (Exception ex) { - logger.warn("Error occurred in file watcher. ", ex); - } - } - } - - //endregion - - //region private classes - - private static final class FileChangeListenerList { - private ArrayList> listeners = new ArrayList<>(); - - public void addListener(FileListener listener) { - listeners.add(new WeakReference<>(listener)); - } - - public void notify(Path path, WatchEvent.Kind kind) { - ArrayList> toRemove = new ArrayList<>(); - for (WeakReference listenerWeakReference : listeners) { - FileListener listener = listenerWeakReference.get(); - if (listener == null) { - toRemove.add(listenerWeakReference); - } - else { - try { - listener.onFileChanged(path, kind); - } - catch (Exception ex) { - logger.warn("Error occurred in file watcher. ", ex); - } - } - } - listeners.removeAll(toRemove); - } - } - - private static final class FileChangeListenerMap { - private ConcurrentHashMap listeners = new ConcurrentHashMap<>(); - - public void addListener(WatchKey watchKey, FileListener listener) { - FileChangeListenerList list = listeners.get(watchKey); - if (list == null) { - final FileChangeListenerList newList = new FileChangeListenerList(); - list = listeners.putIfAbsent(watchKey, newList); - if (list == null) { - list = newList; - } - } - list.addListener(listener); - } - - public void notify(WatchKey watchKey, Path path, WatchEvent.Kind kind) { - FileChangeListenerList list = listeners.get(watchKey); - if (list != null) { - list.notify(path, kind); - } - } - } - - //endregion -} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java index 2a846178bd3d..9ee8264fcbb1 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java @@ -6,47 +6,25 @@ import org.springframework.vault.support.VaultResponse; import java.net.URI; -import java.util.List; import java.util.Map; import java.util.Properties; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.io.*; public class VaultServiceImpl { private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; - private static final String ENV_VAULT_AUTH_PATH = "VAULT_AUTH_PATH"; private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; private static final String ENV_VAULT_PATH = "VAULT_PATH"; private static final String DATA = "data"; - private static final String vaultTokenFilePath = System.getenv().getOrDefault(ENV_VAULT_AUTH_PATH, "/etc/vault/token"); + private VaultTemplate vaultTemplate; - private String vaultToken; - private String vaultHost; public VaultServiceImpl() { try { - vaultToken = getVaultToken(); - vaultHost = System.getenv(ENV_VAULT_ADDR); + String vaultToken = System.getenv(ENV_VAULT_TOKEN); + String vaultHost = System.getenv(ENV_VAULT_ADDR); vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); } catch (Exception e) { throw new RuntimeException("Failed to connect to vault using token", e); } - watchVaultFileUpdates(); - } - - private String getVaultToken() { - try { - List lines = Files.readAllLines(Paths.get(vaultTokenFilePath)); - if (!lines.isEmpty()) { - return lines.get(0); - } else { - throw new RuntimeException(vaultTokenFilePath + ": vault auth token file is empty."); - } - } catch (IOException e) { - throw new RuntimeException("Error reading vault auth token file", e); - } } public Properties readVaultProperties() { @@ -80,15 +58,4 @@ private static Properties readVaultProperties(VaultResponse vaultResponse) { return new Properties(); } - - private void watchVaultFileUpdates() { - FileWatcher.getInstance().addListener(Paths.get(vaultTokenFilePath).getParent(), (path, kind) -> { - vaultToken = getVaultToken(); - try { - vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); - } catch (Exception e) { - throw new RuntimeException("vault configuration is wrong", e); - } - }); - } } From 01c25178a380ab7f37b8ac5a19436163c866bd01 Mon Sep 17 00:00:00 2001 From: Puru Yanamala Date: Fri, 3 May 2024 12:25:01 +0100 Subject: [PATCH 5/6] [GENE-2434] - Vault token read from file. --- lucene/default-nested-ivy-settings.xml | 2 +- .../solr/handler/dataimport/FileWatcher.java | 184 ++++++++++++++++++ .../handler/dataimport/VaultServiceImpl.java | 39 +++- 3 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java diff --git a/lucene/default-nested-ivy-settings.xml b/lucene/default-nested-ivy-settings.xml index c9fe95be0ce3..9961a4d33c4d 100644 --- a/lucene/default-nested-ivy-settings.xml +++ b/lucene/default-nested-ivy-settings.xml @@ -33,7 +33,7 @@ - + diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java new file mode 100644 index 000000000000..c0ddec7d5acf --- /dev/null +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/FileWatcher.java @@ -0,0 +1,184 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (C) 2014 SilkCloud and/or its affiliates. All rights reserved. + */ + +package org.apache.solr.handler.dataimport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; +import static java.nio.file.StandardWatchEventKinds.*; + +/** + * Java doc. + */ +public class FileWatcher { + //region singleton + private static volatile FileWatcher instance; + + public static FileWatcher getInstance() { + // lazy singleton + if (instance == null) { + synchronized (FileWatcher.class) { + if (instance == null) { + FileWatcher instance = new FileWatcher(); + instance.initialize(); + FileWatcher.instance = instance; + } + } + } + return instance; + } + + public static void setInstance(FileWatcher watcher) { + // setInstance for unit testing + instance = watcher; + } + //endregion + + //region private fields + private static Logger logger = LoggerFactory.getLogger(FileWatcher.class); + + private Thread thread; + private WatchService watchService; + private FileChangeListenerMap listeners = new FileChangeListenerMap(); + //endregion + + /**. + * File listener + */ + public interface FileListener { + void onFileChanged(Path path, WatchEvent.Kind kind); + } + + public FileWatcher addListener(Path path, FileListener listener) { + try { + WatchKey key = path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY); + listeners.addListener(key, listener); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + + return this; + } + + public void close() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + + //region private methods + + // protected empty constructor for subclassing/mocking + protected FileWatcher() { + } + + private void initialize() { + try { + watchService = FileSystems.getDefault().newWatchService(); + } + catch (IOException ex) { + throw new RuntimeException("Error creating watch service.", ex); + } + thread = new Thread(new Runnable() { + @Override + public void run() { + FileWatcher.this.run(); + } + }); + thread.start(); + } + + private void run() { + for (; ; ) { + try { + WatchKey key = watchService.take(); + Path path = (Path) key.watchable(); + + for (WatchEvent event : key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + + if (kind == StandardWatchEventKinds.OVERFLOW) { + logger.warn("Overflow happened in FileWatcher for key " + key); + continue; + } + + WatchEvent ev = (WatchEvent) event; + listeners.notify(key, path, ev.kind()); + } + } + catch (InterruptedException ex) { + return; + } + catch (Exception ex) { + logger.warn("Error occurred in file watcher. ", ex); + } + } + } + + //endregion + + //region private classes + + private static final class FileChangeListenerList { + private ArrayList> listeners = new ArrayList<>(); + + public void addListener(FileListener listener) { + listeners.add(new WeakReference<>(listener)); + } + + public void notify(Path path, WatchEvent.Kind kind) { + ArrayList> toRemove = new ArrayList<>(); + for (WeakReference listenerWeakReference : listeners) { + FileListener listener = listenerWeakReference.get(); + if (listener == null) { + toRemove.add(listenerWeakReference); + } + else { + try { + listener.onFileChanged(path, kind); + } + catch (Exception ex) { + logger.warn("Error occurred in file watcher. ", ex); + } + } + } + listeners.removeAll(toRemove); + } + } + + private static final class FileChangeListenerMap { + private ConcurrentHashMap listeners = new ConcurrentHashMap<>(); + + public void addListener(WatchKey watchKey, FileListener listener) { + FileChangeListenerList list = listeners.get(watchKey); + if (list == null) { + final FileChangeListenerList newList = new FileChangeListenerList(); + list = listeners.putIfAbsent(watchKey, newList); + if (list == null) { + list = newList; + } + } + list.addListener(listener); + } + + public void notify(WatchKey watchKey, Path path, WatchEvent.Kind kind) { + FileChangeListenerList list = listeners.get(watchKey); + if (list != null) { + list.notify(path, kind); + } + } + } + + //endregion +} diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java index 9ee8264fcbb1..2a846178bd3d 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/VaultServiceImpl.java @@ -6,25 +6,47 @@ import org.springframework.vault.support.VaultResponse; import java.net.URI; +import java.util.List; import java.util.Map; import java.util.Properties; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.io.*; public class VaultServiceImpl { private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; + private static final String ENV_VAULT_AUTH_PATH = "VAULT_AUTH_PATH"; private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; private static final String ENV_VAULT_PATH = "VAULT_PATH"; private static final String DATA = "data"; - + private static final String vaultTokenFilePath = System.getenv().getOrDefault(ENV_VAULT_AUTH_PATH, "/etc/vault/token"); private VaultTemplate vaultTemplate; + private String vaultToken; + private String vaultHost; public VaultServiceImpl() { try { - String vaultToken = System.getenv(ENV_VAULT_TOKEN); - String vaultHost = System.getenv(ENV_VAULT_ADDR); + vaultToken = getVaultToken(); + vaultHost = System.getenv(ENV_VAULT_ADDR); vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); } catch (Exception e) { throw new RuntimeException("Failed to connect to vault using token", e); } + watchVaultFileUpdates(); + } + + private String getVaultToken() { + try { + List lines = Files.readAllLines(Paths.get(vaultTokenFilePath)); + if (!lines.isEmpty()) { + return lines.get(0); + } else { + throw new RuntimeException(vaultTokenFilePath + ": vault auth token file is empty."); + } + } catch (IOException e) { + throw new RuntimeException("Error reading vault auth token file", e); + } } public Properties readVaultProperties() { @@ -58,4 +80,15 @@ private static Properties readVaultProperties(VaultResponse vaultResponse) { return new Properties(); } + + private void watchVaultFileUpdates() { + FileWatcher.getInstance().addListener(Paths.get(vaultTokenFilePath).getParent(), (path, kind) -> { + vaultToken = getVaultToken(); + try { + vaultTemplate = new VaultTemplate(VaultEndpoint.from(new URI(vaultHost)), new TokenAuthentication(vaultToken)); + } catch (Exception e) { + throw new RuntimeException("vault configuration is wrong", e); + } + }); + } } From a88e08530c74957f5ebe3ef916800981790ca78f Mon Sep 17 00:00:00 2001 From: Emily Nicholson Date: Mon, 8 Jul 2024 10:29:10 -0700 Subject: [PATCH 6/6] GENE-2727: Onboard this repo to Sonarqube https://jira.unity3d.com/browse/GENE-2727 --- .github/workflows/sonarqube.yml | 18 ++++++++++++++++++ sonar-project.properties | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 .github/workflows/sonarqube.yml create mode 100644 sonar-project.properties diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml new file mode 100644 index 000000000000..1d7051c8ecca --- /dev/null +++ b/.github/workflows/sonarqube.yml @@ -0,0 +1,18 @@ +name: SonarQube + +on: + push: + branches: + - branch_8_3 + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + sonarqube: + uses: Unity-Technologies/github-actions-workflows/.github/workflows/sonarqube.yml@main + with: + coverage: false \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000000..ec32258512c2 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,7 @@ +sonar.projectKey=lucene-solr +sonar.projectName=lucene-solr +sonar.projectVersion=1.0 + +sonar.links.scm=https://github.com/Unity-Technologies/lucene-solr +sonar.pullrequest.github.repository=Unity-Technologies/lucene-solr +sonar.exclusions=**/*.test.js,frontend_tests/**,docs/** \ No newline at end of file