You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ro...@apache.org on 2021/05/09 19:42:09 UTC
[felix-dev] branch master updated: [FELIX-6414] Interpolation
plugin support multiple secrets directories
This is an automated email from the ASF dual-hosted git repository.
rotty3000 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new afa3924 [FELIX-6414] Interpolation plugin support multiple secrets directories
afa3924 is described below
commit afa392414c8939e3f4dd73939621fb22aefbf47c
Author: Raymond Augé <ro...@apache.org>
AuthorDate: Sun May 9 15:41:41 2021 -0400
[FELIX-6414] Interpolation plugin support multiple secrets directories
Signed-off-by: Raymond Augé <ro...@apache.org>
---
configadmin-plugins/interpolation/README.md | 4 +--
.../InterpolationConfigurationPlugin.java | 27 ++++++++++++------
.../InterpolationConfigurationPluginTest.java | 32 +++++++++++++++++-----
.../interpolation/src/test/resources/foo.bar | 1 +
.../src/test/resources/{ => other}/testfile.txt | 0
5 files changed, 46 insertions(+), 18 deletions(-)
diff --git a/configadmin-plugins/interpolation/README.md b/configadmin-plugins/interpolation/README.md
index 868ea0f..d6605fc 100644
--- a/configadmin-plugins/interpolation/README.md
+++ b/configadmin-plugins/interpolation/README.md
@@ -109,12 +109,12 @@ In case of the Apache Felix ConfigAdmin implementation, this can be achieved by
### Secrets lookup
-In order to look up secrets on the filesystem, the plugin must be provided with the directory
+In order to look up secrets on the filesystem, the plugin must be provided with the directories
where these can be found.
This is done through the following property:
-* `org.apache.felix.configadmin.plugin.interpolation.secretsdir`: specify the directory where the files used for the file-based interpolation, such as Kubernetes secrets, are mounted.
+* `org.apache.felix.configadmin.plugin.interpolation.secretsdir`: specify a comma-separated (`,`) list of directories where the files used for the file-based interpolation, such as Kubernetes secrets, are mounted.
If the property is not present, the plugin will function, but without being able to replace values based on secrets.
diff --git a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
index 97656ae..4974848 100644
--- a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
+++ b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
@@ -16,17 +16,22 @@
*/
package org.apache.felix.configadmin.plugin.interpolation;
+import static java.util.stream.Collectors.toList;
+
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -91,17 +96,17 @@ class InterpolationConfigurationPlugin implements ConfigurationPlugin {
}
private final BundleContext context;
- private final File directory;
+ private final List<File> directory;
private final Charset encodingCharset;
InterpolationConfigurationPlugin(BundleContext bc, String dir, String fileEncoding) {
context = bc;
if (dir != null) {
- directory = new File(dir);
+ directory = Stream.of(dir.split("\\s*,\\s*")).map(File::new).collect(toList());
getLog().info("Configured directory for secrets: {}", dir);
} else {
- directory = null;
+ directory = Collections.emptyList();
}
if (fileEncoding == null) {
encodingCharset = Charset.defaultCharset();
@@ -188,7 +193,7 @@ class InterpolationConfigurationPlugin implements ConfigurationPlugin {
}
String getVariableFromFile(final String key, final String name, final Object pid) {
- if (directory == null) {
+ if (directory.isEmpty()) {
getLog().warn("Cannot replace property value {} for PID {}. No directory configured via framework property " +
Activator.DIR_PROPERTY, key, pid);
return null;
@@ -199,17 +204,21 @@ class InterpolationConfigurationPlugin implements ConfigurationPlugin {
return null;
}
- File file = new File(directory, name);
- if (!file.isFile()) {
- getLog().warn("Cannot replace variable. Configured path is not a regular file: " + file);
+ List<File> files = directory.stream().map(d -> new File(d, name)).filter(File::exists).collect(toList());
+ if (files.stream().noneMatch(File::isFile)) {
+ getLog().warn("Cannot replace variable. Configured paths are not regular files: " + files);
return null;
}
- if (!file.getAbsolutePath().startsWith(directory.getAbsolutePath())) {
+ if (files.stream().map(File::getAbsolutePath).noneMatch(s -> directory.stream().anyMatch(dir -> s.startsWith(dir.getAbsolutePath())))) {
getLog().error("Illegal secret location: " + name + " Going out the directory structure is not allowed");
return null;
}
+ File file = files.stream().findFirst().orElseThrow(
+ () -> new IllegalStateException(
+ "Something went terribly wrong. This should not be possible."));
+
byte[] bytes;
try {
bytes = Files.readAllBytes(file.toPath());
@@ -253,7 +262,7 @@ class InterpolationConfigurationPlugin implements ConfigurationPlugin {
* the delimiter (avoiding splitting), unless that backslash is preceded by
* another backslash, in which case the two backslashes are replaced by a single
* one and the value is split after the backslash.
- *
+ *
* @param value The value to split
* @param delimiter The delimiter
* @return The resulting array
diff --git a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
index 7a38573..888f0a5 100644
--- a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
+++ b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
@@ -114,9 +114,10 @@ public class InterpolationConfigurationPluginTest {
@Test
public void testReplacement() throws Exception {
- String rf = getClass().getResource("/testfile.txt").getFile();
+ String rf = getClass().getResource("/other/testfile.txt").getFile();
+ File file = new File(rf);
InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
- new File(rf).getParent(), null);
+ file.getParent() + "," + file.getParentFile().getParent(), null);
assertEquals("xxla la layy", plugin.replace("akey", "xx$[secret:testfile.txt]yy", "apid"));
String doesNotReplace = "xx$[" + rf + "]yy";
@@ -125,9 +126,10 @@ public class InterpolationConfigurationPluginTest {
@Test
public void testNoReplacement() throws IOException {
- String rf = getClass().getResource("/testfile.txt").getFile();
+ String rf = getClass().getResource("/other/testfile.txt").getFile();
+ File file = new File(rf);
InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
- new File(rf).getParent(), null);
+ file.getParent() + "," + file.getParentFile().getParent(), null);
assertEquals("foo", plugin.replace("akey", "foo", "apid"));
}
@@ -187,9 +189,10 @@ public class InterpolationConfigurationPluginTest {
public void testMultiplePlaceholders() throws Exception {
BundleContext bc = Mockito.mock(BundleContext.class);
Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
- String rf = getClass().getResource("/testfile.txt").getFile();
- InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, new File(rf).getParent(),
- null);
+ String rf = getClass().getResource("/other/testfile.txt").getFile();
+ File file = new File(rf);
+ InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc,
+ file.getParent() + "," + file.getParentFile().getParent(), null);
assertEquals("xxhello thereyyhello therezz",
plugin.replace("akey", "xx$[prop:foo.bar]yy$[prop:foo.bar]zz", "apid"));
@@ -199,6 +202,21 @@ public class InterpolationConfigurationPluginTest {
}
@Test
+ public void testMultipleDirectories() throws Exception {
+ BundleContext bc = Mockito.mock(BundleContext.class);
+ String rf = getClass().getResource("/other/testfile.txt").getFile();
+ File file = new File(rf);
+ InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc,
+ file.getParent() + "," + file.getParentFile().getParent(), null);
+
+ assertEquals("xxhello thereyyhello therezz",
+ plugin.replace("akey", "xx$[secret:foo.bar]yy$[secret:foo.bar]zz", "apid"));
+
+ assertEquals("xxla la layyhello therezz",
+ plugin.replace("akey", "xx$[secret:testfile.txt]yy$[secret:foo.bar]zz", "apid"));
+ }
+
+ @Test
public void testNestedPlaceholders() throws Exception {
BundleContext bc = Mockito.mock(BundleContext.class);
Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
diff --git a/configadmin-plugins/interpolation/src/test/resources/foo.bar b/configadmin-plugins/interpolation/src/test/resources/foo.bar
new file mode 100644
index 0000000..d2aeeec
--- /dev/null
+++ b/configadmin-plugins/interpolation/src/test/resources/foo.bar
@@ -0,0 +1 @@
+hello there
\ No newline at end of file
diff --git a/configadmin-plugins/interpolation/src/test/resources/testfile.txt b/configadmin-plugins/interpolation/src/test/resources/other/testfile.txt
similarity index 100%
rename from configadmin-plugins/interpolation/src/test/resources/testfile.txt
rename to configadmin-plugins/interpolation/src/test/resources/other/testfile.txt