openwebbeans-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1780417 - in /openwebbeans/meecrowave/trunk: meecrowave-core/src/main/java/org/apache/meecrowave/ meecrowave-core/src/main/java/org/apache/meecrowave/runner/ meecrowave-core/src/main/java/org/apache/meecrowave/service/ meecrowave-core/src/...
Date Thu, 26 Jan 2017 16:14:01 GMT
Author: rmannibucau
Date: Thu Jan 26 16:14:01 2017
New Revision: 1780417

URL: http://svn.apache.org/viewvc?rev=1780417&view=rev
Log:
MEECROWAVE-12 adding value transformer to cipher passwords

Added:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/ValueTransformer.java
Modified:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
    openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
    openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java?rev=1780417&r1=1780416&r2=1780417&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
(original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
Thu Jan 26 16:14:01 2017
@@ -47,6 +47,7 @@ import org.apache.meecrowave.logging.tom
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 import org.apache.meecrowave.openwebbeans.OWBAutoSetup;
 import org.apache.meecrowave.runner.cli.CliOption;
+import org.apache.meecrowave.service.ValueTransformer;
 import org.apache.meecrowave.tomcat.CDIInstanceManager;
 import org.apache.meecrowave.tomcat.LoggingAccessLogPattern;
 import org.apache.meecrowave.tomcat.NoDescriptorRegistry;
@@ -65,6 +66,8 @@ import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
 import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.BeanManager;
@@ -90,6 +93,7 @@ import java.net.URL;
 import java.net.URLClassLoader;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -97,10 +101,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.stream.Stream;
 
 import static java.util.Collections.emptyList;
@@ -996,6 +1002,7 @@ public class Meecrowave implements AutoC
         private final Map<Class<?>, Object> extensions = new HashMap<>();
 
         public Builder() { // load defaults
+            extensions.put(ValueTransformers.class, new ValueTransformers());
             loadFrom("meecrowave.properties");
         }
 
@@ -1662,12 +1669,14 @@ public class Meecrowave implements AutoC
                     return property == null ? config.getProperty(key) : null;
                 }
             });
+
+            final ValueTransformers transformers = getExtension(ValueTransformers.class);
             for (final String key : config.stringPropertyNames()) {
                 final String val = config.getProperty(key);
                 if (val == null || val.trim().isEmpty()) {
                     continue;
                 }
-                final String newVal = strSubstitutor.replace(config.getProperty(key));
+                final String newVal = transformers.apply(strSubstitutor.replace(config.getProperty(key)));
                 if (!val.equals(newVal)) {
                     config.setProperty(key, newVal);
                 }
@@ -1676,13 +1685,14 @@ public class Meecrowave implements AutoC
             for (final Field field : Builder.class.getDeclaredFields()) {
                 final CliOption annotation = field.getAnnotation(CliOption.class);
                 if (annotation == null) {
-                    return;
+                    continue;
                 }
                 final String name = field.getName();
                 Stream.of(Stream.of(annotation.name()), Stream.of(annotation.alias()))
                         .flatMap(a -> a)
                         .map(config::getProperty)
-                        .findFirst().ifPresent(val -> {
+                        .filter(Objects::nonNull)
+                        .findAny().ifPresent(val -> {
                     final Object toSet;
                     if (field.getType() == String.class) {
                         toSet = val;
@@ -1764,6 +1774,7 @@ public class Meecrowave implements AutoC
         }
 
         public <T> T bind(final T instance) {
+            final ValueTransformers transformers = getExtension(ValueTransformers.class);
             Class<? extends Object> type = instance.getClass();
             do {
                 Stream.of(type.getDeclaredFields())
@@ -1778,6 +1789,8 @@ public class Meecrowave implements AutoC
                                 }
                             }
 
+                            value = transformers.apply(value);
+
                             if (!f.isAccessible()) {
                                 f.setAccessible(true);
                             }
@@ -1810,6 +1823,56 @@ public class Meecrowave implements AutoC
         }
     }
 
+    public static class ValueTransformers implements Function<String, String> {
+        private final Map<String, ValueTransformer> transformers = new HashMap<>();
+
+        @Override
+        public String apply(final String value) {
+            if (value.startsWith("decode:")) {
+                if (transformers.isEmpty()) { // lazy loading
+                    transformers.put("Static3DES", new ValueTransformer() { // compatibility
with tomee
+                        private final SecretKeySpec key = new SecretKeySpec(new byte[]{
+                                (byte) 0x76, (byte) 0x6F, (byte) 0xBA, (byte) 0x39, (byte)
0x31,
+                                (byte) 0x2F, (byte) 0x0D, (byte) 0x4A, (byte) 0xA3, (byte)
0x90,
+                                (byte) 0x55, (byte) 0xFE, (byte) 0x55, (byte) 0x65, (byte)
0x61,
+                                (byte) 0x13, (byte) 0x34, (byte) 0x82, (byte) 0x12, (byte)
0x17,
+                                (byte) 0xAC, (byte) 0x77, (byte) 0x39, (byte) 0x19}, "DESede");
+
+                        @Override
+                        public String name() {
+                            return "Static3DES";
+                        }
+
+                        @Override
+                        public String apply(final String encodedPassword) {
+                            Objects.requireNonNull(encodedPassword, "value can't be null");
+                            try {
+                                final byte[] cipherText = Base64.getDecoder().decode(encodedPassword);
+                                final Cipher cipher = Cipher.getInstance("DESede");
+                                cipher.init(Cipher.DECRYPT_MODE, key);
+                                return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8);
+                            } catch (final Exception e) {
+                                throw new IllegalArgumentException(e);
+                            }
+                        }
+                    });
+                    for (final ValueTransformer t : ServiceLoader.load(ValueTransformer.class))
{
+                        transformers.put(t.name(), t);
+                    }
+                }
+
+                final String substring = value.substring("decode:".length());
+                final int sep = substring.indexOf(':');
+                if (sep < 0) {
+                    throw new IllegalArgumentException("No transformer algorithm for " +
value);
+                }
+                final String algo = substring.substring(0, sep);
+                return Objects.requireNonNull(transformers.get(algo), "No ValueTransformer
for value '" + value + "'").apply(substring.substring(sep + 1));
+            }
+            return value;
+        }
+    }
+
     public static class LoginConfigBuilder {
         private final LoginConfig loginConfig = new LoginConfig();
 

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java?rev=1780417&r1=1780416&r2=1780417&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
(original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
Thu Jan 26 16:14:01 2017
@@ -37,6 +37,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.ServiceLoader;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -106,15 +107,15 @@ public class Cli {
     private static Meecrowave.Builder buildConfig(final CommandLine line, final List<Field>
fields,
                                                   final Map<Object, List<Field>>
propertiesOptions) {
         final Meecrowave.Builder config = new Meecrowave.Builder();
-        bind(line, fields, config);
+        bind(config, line, fields, config);
         propertiesOptions.forEach((o, f) -> {
-            bind(line, f, o);
+            bind(config, line, f, o);
             config.setExtension(o.getClass(), o);
         });
         return config;
     }
 
-    private static void bind(final CommandLine line, final List<Field> fields, final
Object config) {
+    private static void bind(final Meecrowave.Builder builder, final CommandLine line, final
List<Field> fields, final Object config) {
         fields.forEach(f -> {
             final CliOption opt = f.getAnnotation(CliOption.class);
             final Optional<String> first = Stream.of(Stream.of(opt.name()), Stream.of(opt.alias()))
@@ -125,7 +126,7 @@ public class Cli {
                 final String name = first.get();
                 ofNullable(f.getType() == boolean.class ?
                         ofNullable(line.getOptionValue(name)).map(Boolean::parseBoolean).orElse(true)
:
-                        toValue(name, line.getOptionValues(name), f.getType()))
+                        toValue(builder, name, line.getOptionValues(name), f.getType()))
                         .ifPresent(v -> {
                             if (!f.isAccessible()) {
                                 f.setAccessible(true);
@@ -140,10 +141,15 @@ public class Cli {
         });
     }
 
-    private static Object toValue(final String name, final String[] optionValues, final Class<?>
type) {
+    private static Object toValue(final Meecrowave.Builder builder, final String name, final
String[] optionValues, final Class<?> type) {
         if (optionValues == null || optionValues.length == 0) {
             return null;
         }
+
+        // decode options while it is strings
+        IntStream.range(0, optionValues.length)
+                .forEach(i -> optionValues[i] = builder.getExtension(Meecrowave.ValueTransformers.class).apply(optionValues[i]));
+
         if (String.class == type) {
             return optionValues[0];
         }

Added: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/ValueTransformer.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/ValueTransformer.java?rev=1780417&view=auto
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/ValueTransformer.java
(added)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/service/ValueTransformer.java
Thu Jan 26 16:14:01 2017
@@ -0,0 +1,32 @@
+/*
+ * 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.meecrowave.service;
+
+import java.util.function.Function;
+
+/**
+ * Implementation transforming a configuration value to a clear value.
+ * Ex: --foo=decode:bar:val will decode val with the ValueTransformer bar (name).
+ */
+public interface ValueTransformer extends Function<String, String> {
+    /**
+     * @return name used to mark this transformer in values.
+     */
+    String name();
+}

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java?rev=1780417&r1=1780416&r2=1780417&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
(original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
Thu Jan 26 16:14:01 2017
@@ -33,6 +33,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Writer;
 import java.net.URL;
+import java.util.Properties;
 import java.util.stream.Stream;
 
 import static org.junit.Assert.assertEquals;
@@ -59,6 +60,22 @@ public class MeecrowaveTest {
     }
 
     @Test
+    public void valueTransformationMainConfig() {
+        assertEquals(1234, new Meecrowave.Builder() {{
+            loadFromProperties(new Properties() {{
+                setProperty("http", "decode:Static3DES:+yYyC7Lb5+k=");
+            }});
+        }}.getHttpPort());
+    }
+
+    @Test
+    public void valueTransformationExtension() {
+        assertEquals(1234, new Meecrowave.Builder()
+                .property("my-prefix-port", "decode:Static3DES:+yYyC7Lb5+k=")
+                .bind(new MyConfig()).port);
+    }
+
+    @Test
     public void simpleWebapp() {
         final File root = new File("target/MeecrowaveTest/simpleWebapp/app");
         FileUtils.mkDir(root);

Modified: openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc?rev=1780417&r1=1780416&r2=1780417&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
(original)
+++ openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
Thu Jan 26 16:14:01 2017
@@ -64,3 +64,32 @@ TIP: out of the box, any `Builder` insta
 
 Meecrowave relies by default on Log4j2 (see http://logging.apache.org/log4j/2.x/). By default
it uses an internal
 configuration which is overriden by standard log4j mecanism.
+
+== Passwords/Secrets
+
+For the configuration requiring to be ciphered you can implement `org.apache.meecrowave.service.ValueTransformer`:
+
+[source]
+----
+public class MyTransformer implements ValueTransformer {
+    @Override
+    public String name() {
+        return "mine";
+    }
+
+    @Override
+    public String apply(final String encodedPassword) {
+        return ....;
+    }
+}
+----
+
+NOTE: this code being executed before the container starts you can't use CDI there.
+
+To register your implementation just put the fully qualified name of your transformer in
`META-INF/services/org.apache.meecrowave.service.ValueTransformer`.
+
+Then to use it set the value to `decode:mine:encodedvalue`. General pattern is: `decode:<transformer
name>:<value before decryption>`.
+
+Note that by default the same ciphering algorithm than in TomEE is available (Static3DES).
+
+This syntax is usable on the command line and in `meecrowave.properties`.



Mime
View raw message