This is an automated email from the ASF dual-hosted git repository.
jihoonson pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 23d7d71 Add Environment Variable DynamicConfigProvider (#11377)
23d7d71 is described below
commit 23d7d71ea5cb104b47f46b8bed359687f9ebc86c
Author: Yi Yuan <[email protected]>
AuthorDate: Thu Aug 5 11:26:58 2021 +0800
Add Environment Variable DynamicConfigProvider (#11377)
* add_environment_variable_DynamicConfigProvider
* fix code
* code fixed
* code fixed
* add document
* fix doc
* fix doc
* add more unit test
* fix style
* fix document
* bug fixed
* fix unit test
* fix comment
* fix test
Co-authored-by: yuanyi <[email protected]>
---
.../druid/metadata/DynamicConfigProvider.java | 1 +
.../EnvironmentVariableDynamicConfigProvider.java | 89 +++++++++++++++++
...vironmentVariableDynamicConfigProviderTest.java | 109 +++++++++++++++++++++
docs/operations/dynamic-config-provider.md | 13 +++
4 files changed, 212 insertions(+)
diff --git
a/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java
b/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java
index 52f032a..166437c 100644
--- a/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java
+++ b/core/src/main/java/org/apache/druid/metadata/DynamicConfigProvider.java
@@ -32,6 +32,7 @@ import java.util.Map;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl =
MapStringDynamicConfigProvider.class)
@JsonSubTypes(value = {
@JsonSubTypes.Type(name = "mapString", value =
MapStringDynamicConfigProvider.class),
+ @JsonSubTypes.Type(name = "environment", value =
EnvironmentVariableDynamicConfigProvider.class)
})
public interface DynamicConfigProvider<T>
{
diff --git
a/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java
b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java
new file mode 100644
index 0000000..629c748
--- /dev/null
+++
b/core/src/main/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProvider.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.metadata;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class EnvironmentVariableDynamicConfigProvider implements
DynamicConfigProvider<String>
+{
+ private final ImmutableMap<String, String> variables;
+
+ @JsonCreator
+ public EnvironmentVariableDynamicConfigProvider(
+ @JsonProperty("variables") Map<String, String> config
+ )
+ {
+ this.variables = ImmutableMap.copyOf(Preconditions.checkNotNull(config,
"config"));
+ }
+
+ @JsonProperty("variables")
+ public Map<String, String> getVariables()
+ {
+ return variables;
+ }
+
+ @Override
+ public Map<String, String> getConfig()
+ {
+ HashMap<String, String> map = new HashMap<>();
+ for (Map.Entry<String, String> entry : variables.entrySet()) {
+ map.put(entry.getKey(), System.getenv(entry.getValue()));
+ }
+ return map;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "EnvironmentVariablePasswordProvider{" +
+ "variable='" + variables + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ EnvironmentVariableDynamicConfigProvider that =
(EnvironmentVariableDynamicConfigProvider) o;
+
+ return Objects.equals(variables, that.variables);
+
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return variables.hashCode();
+ }
+
+}
diff --git
a/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java
b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java
new file mode 100644
index 0000000..94f408d
--- /dev/null
+++
b/core/src/test/java/org/apache/druid/metadata/EnvironmentVariableDynamicConfigProviderTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.metadata;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class EnvironmentVariableDynamicConfigProviderTest
+{
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ private static final Map<String, String> CHANGED_ENV_MAP = new HashMap<>();
+
+ @BeforeClass
+ public static void setupTest() throws Exception
+ {
+ Map<String, String> oldEnvMap = getENVMap();
+ Map<String, String> addEnvMap = ImmutableMap.of("DRUID_USER", "druid",
"DRUID_PASSWORD", "123");
+ for (Map.Entry<String, String> entry : addEnvMap.entrySet()) {
+ CHANGED_ENV_MAP.put(entry.getKey(), oldEnvMap.get(entry.getKey()));
+ oldEnvMap.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @AfterClass
+ public static void tearDownTest() throws Exception
+ {
+ Map<String, String> oldEnvMap = getENVMap();
+ for (Map.Entry<String, String> entry : CHANGED_ENV_MAP.entrySet()) {
+ if (entry.getValue() == null) {
+ oldEnvMap.remove(entry.getKey());
+ } else {
+ oldEnvMap.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ @Test
+ public void testSerde() throws IOException
+ {
+ String providerString = "{\"type\": \"environment\", \"variables\" :
{\"testKey\":\"testValue\"}}";
+ DynamicConfigProvider provider = JSON_MAPPER.readValue(providerString,
DynamicConfigProvider.class);
+ Assert.assertTrue(provider instanceof
EnvironmentVariableDynamicConfigProvider);
+ Assert.assertEquals("testValue",
((EnvironmentVariableDynamicConfigProvider)
provider).getVariables().get("testKey"));
+ DynamicConfigProvider serde =
JSON_MAPPER.readValue(JSON_MAPPER.writeValueAsString(provider),
DynamicConfigProvider.class);
+ Assert.assertEquals(provider, serde);
+ }
+
+ @Test
+ public void testGetConfig() throws Exception
+ {
+ String providerString = "{\"type\": \"environment\", \"variables\" :
{\"user\":\"DRUID_USER\",\"password\":\"DRUID_PASSWORD\"}}";
+ DynamicConfigProvider provider = JSON_MAPPER.readValue(providerString,
DynamicConfigProvider.class);
+ Assert.assertTrue(provider instanceof
EnvironmentVariableDynamicConfigProvider);
+ Assert.assertEquals("druid", ((EnvironmentVariableDynamicConfigProvider)
provider).getConfig().get("user"));
+ Assert.assertEquals("123", ((EnvironmentVariableDynamicConfigProvider)
provider).getConfig().get("password"));
+ }
+
+ /**
+ * This method use reflection to get system environment variables map in
runtime JVM
+ * which can be changed.
+ *
+ * @return system environment variables map.
+ */
+ private static Map<String, String> getENVMap() throws Exception
+ {
+ Map<String, String> envMap = null;
+ Class[] classes = Collections.class.getDeclaredClasses();
+ Map<String, String> systemEnv = System.getenv();
+ for (Class cl : classes) {
+ if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Object object = field.get(systemEnv);
+ envMap = (Map<String, String>) object;
+ }
+ }
+ if (envMap == null) {
+ throw new RuntimeException("Failed to get environment map.");
+ }
+ return envMap;
+ }
+}
diff --git a/docs/operations/dynamic-config-provider.md
b/docs/operations/dynamic-config-provider.md
index 33bf966..45b61d5 100644
--- a/docs/operations/dynamic-config-provider.md
+++ b/docs/operations/dynamic-config-provider.md
@@ -31,3 +31,16 @@ Users can create custom extension of the
`DynamicConfigProvider` interface that
For more information, see [Adding a new DynamicConfigProvider
implementation](../development/modules.md#adding-a-new-dynamicconfigprovider-implementation).
+## Environment variable dynamic config provider
+
+`EnvironmentVariableDynamicConfigProvider` can be used to avoid exposing
credentials or other secret information in the configuration files using
environment variables. An example to use this `configProvider` is:
+```json
+druid.some.config.dynamicConfigProvider={"type":
"environment","variables":{"secret1": "SECRET1_VAR","secret2": "SECRET2_VAR"}}
+```
+The values are described below.
+
+|Field|Type|Description|Required|
+|-----|----|-----------|--------|
+|`type`|String|dynamic config provider type|Yes: `environment`|
+|`variables`|Map|environment variables to get information from|Yes|
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]