qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rgodf...@apache.org
Subject svn commit: r1618815 - in /qpid/trunk/qpid/java: broker-core/src/main/java/org/apache/qpid/server/model/ broker-core/src/main/java/org/apache/qpid/server/model/adapter/ broker-core/src/main/java/org/apache/qpid/server/plugin/ broker-core/src/main/java/...
Date Tue, 19 Aug 2014 07:25:27 GMT
Author: rgodfrey
Date: Tue Aug 19 07:25:26 2014
New Revision: 1618815

URL: http://svn.apache.org/r1618815
Log:
QPID-6017 : [Jaa Broker] Provide a mechanism by which "secure" attributes in the configuration
can be encrypted

Added:
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfigurationSecretEncrypterFactory.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/ConfigurationSecretEncrypter.java
Modified:
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/GenericRecoverer.java
    qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
    qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
(original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
Tue Aug 19 07:25:26 2014
@@ -64,6 +64,7 @@ import org.apache.qpid.server.configurat
 import org.apache.qpid.server.configuration.updater.VoidTaskWithException;
 import org.apache.qpid.server.security.SecurityManager;
 import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.encryption.ConfigurationSecretEncrypter;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.util.Action;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -89,6 +90,8 @@ public abstract class AbstractConfigured
         SECURE_VALUES = Collections.unmodifiableMap(secureValues);
     }
 
+    private ConfigurationSecretEncrypter _encrypter;
+
     private enum DynamicState { UNINIT, OPENED, CLOSED };
     private final AtomicReference<DynamicState> _dynamicState = new AtomicReference<>(DynamicState.UNINIT);
 
@@ -201,6 +204,16 @@ public abstract class AbstractConfigured
         _automatedFields = model.getTypeRegistry().getAutomatedFields(getClass());
         _stateChangeMethods = model.getTypeRegistry().getStateChangeMethods(getClass());
 
+
+        for(ConfiguredObject<?> parent : parents.values())
+        {
+            if(parent instanceof AbstractConfiguredObject && ((AbstractConfiguredObject)parent)._encrypter
!= null)
+            {
+                _encrypter = ((AbstractConfiguredObject)parent)._encrypter;
+                break;
+            }
+        }
+
         Object idObj = attributes.get(ID);
 
         UUID uuid;
@@ -541,6 +554,7 @@ public abstract class AbstractConfigured
         if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
         {
             onResolve();
+            postResolve();
             applyToChildren(new Action<ConfiguredObject<?>>()
             {
                 @Override
@@ -555,6 +569,10 @@ public abstract class AbstractConfigured
         }
     }
 
+    protected void postResolve()
+    {
+    }
+
     protected final void doCreation(final boolean skipCheck)
     {
         if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
@@ -593,6 +611,11 @@ public abstract class AbstractConfigured
     {
     }
 
+    protected void setEncrypter(final ConfigurationSecretEncrypter encrypter)
+    {
+        _encrypter = encrypter;
+    }
+
     protected void onResolve()
     {
         Set<ConfiguredObjectAttribute<?,?>> unresolved = new HashSet<>();
@@ -1094,6 +1117,26 @@ public abstract class AbstractConfigured
                                     {
                                         value = ((ConfiguredObject)value).getId();
                                     }
+                                    if(attr.isSecure() && _encrypter != null &&
value != null)
+                                    {
+                                        if(value instanceof Collection || value instanceof
Map)
+                                        {
+                                            ObjectMapper mapper = new ObjectMapper();
+                                            try(StringWriter stringWriter = new StringWriter())
+                                            {
+                                                mapper.writeValue(stringWriter, value);
+                                                value = _encrypter.encrypt(stringWriter.toString());
+                                            }
+                                            catch (IOException e)
+                                            {
+                                                throw new IllegalConfigurationException("Failure
when encrypting a secret value", e);
+                                            }
+                                        }
+                                        else
+                                        {
+                                            value = _encrypter.encrypt(value.toString());
+                                        }
+                                    }
                                     attributes.put(attr.getName(), value);
                                 }
                             }
@@ -1427,6 +1470,27 @@ public abstract class AbstractConfigured
         return false;
     }
 
+    @Override
+    public void decryptSecrets()
+    {
+        if(_encrypter != null)
+        {
+            for (Map.Entry<String, Object> entry : _attributes.entrySet())
+            {
+                ConfiguredObjectAttribute<X, ?> attr =
+                        (ConfiguredObjectAttribute<X, ?>) _attributeTypes.get(entry.getKey());
+                if (attr != null
+                    && attr.isSecure()
+                    && entry.getValue() instanceof String)
+                {
+                    String decrypt = _encrypter.decrypt((String) entry.getValue());
+                    entry.setValue(decrypt);
+                }
+
+            }
+        }
+    }
+
     //=========================================================================================
 
     static String interpolate(ConfiguredObject<?> object, String value)

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
(original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
Tue Aug 19 07:25:26 2014
@@ -51,6 +51,7 @@ public interface Broker<X extends Broker
     String STORE_VERSION = "storeVersion";
     String STORE_PATH = "storePath";
     String MODEL_VERSION = "modelVersion";
+    String CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER = "confidentialConfigurationEncryptionProvider";
 
     String CONNECTION_SESSION_COUNT_LIMIT = "connection.sessionCountLimit";
     String CONNECTION_HEART_BEAT_DELAY = "connection.heartBeatDelay";
@@ -139,6 +140,8 @@ public interface Broker<X extends Broker
     @ManagedContextDefault(name = MESSAGE_COMPRESSION_THRESHOLD_SIZE)
     int DEFAULT_MESSAGE_COMPRESSION_THRESHOLD_SIZE = 102400;
 
+    @ManagedAttribute
+    String getConfidentialConfigurationEncryptionProvider();
 
     @DerivedAttribute( persist = true )
     String getModelVersion();

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
(original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
Tue Aug 19 07:25:26 2014
@@ -253,4 +253,6 @@ public interface ConfiguredObject<X exte
     Model getModel();
 
     void delete();
+
+    void decryptSecrets();
 }

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
(original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
Tue Aug 19 07:25:26 2014
@@ -47,6 +47,8 @@ import org.apache.qpid.server.logging.me
 import org.apache.qpid.server.logging.messages.VirtualHostMessages;
 import org.apache.qpid.server.model.*;
 import org.apache.qpid.server.model.port.AbstractPortWithAuthProvider;
+import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
+import org.apache.qpid.server.plugin.PluggableFactoryLoader;
 import org.apache.qpid.server.security.SecurityManager;
 import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.server.security.access.Operation;
@@ -94,6 +96,8 @@ public class BrokerAdapter extends Abstr
     private boolean _statisticsReportingResetEnabled;
     @ManagedAttributeField
     private boolean _messageCompressionEnabled;
+    @ManagedAttributeField
+    private String _confidentialConfigurationEncryptionProvider;
 
     private State _state = State.UNINITIALIZED;
 
@@ -122,6 +126,25 @@ public class BrokerAdapter extends Abstr
         _dataReceived = new StatisticsCounter("bytes-received");
     }
 
+    @Override
+    protected void postResolve()
+    {
+        super.postResolve();
+        if(_confidentialConfigurationEncryptionProvider != null)
+        {
+
+            PluggableFactoryLoader<ConfigurationSecretEncrypterFactory> factoryLoader
=
+                    new PluggableFactoryLoader<>(ConfigurationSecretEncrypterFactory.class);
+            ConfigurationSecretEncrypterFactory factory = factoryLoader.get(_confidentialConfigurationEncryptionProvider);
+            if(factory == null)
+            {
+                throw new IllegalConfigurationException("Unknown Configuration Secret Encryption
method " + _confidentialConfigurationEncryptionProvider);
+            }
+            setEncrypter(factory.createEncrypter(this));
+        }
+
+    }
+
     public void onValidate()
     {
         super.onValidate();
@@ -368,6 +391,12 @@ public class BrokerAdapter extends Abstr
     }
 
     @Override
+    public String getConfidentialConfigurationEncryptionProvider()
+    {
+        return _confidentialConfigurationEncryptionProvider;
+    }
+
+    @Override
     public String getModelVersion()
     {
         return BrokerModel.MODEL_VERSION;

Added: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfigurationSecretEncrypterFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfigurationSecretEncrypterFactory.java?rev=1618815&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfigurationSecretEncrypterFactory.java
(added)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfigurationSecretEncrypterFactory.java
Tue Aug 19 07:25:26 2014
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.qpid.server.plugin;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.security.encryption.ConfigurationSecretEncrypter;
+
+public interface ConfigurationSecretEncrypterFactory extends Pluggable
+{
+    public ConfigurationSecretEncrypter createEncrypter(ConfiguredObject<?> object);
+}

Added: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java?rev=1618815&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
(added)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
Tue Aug 19 07:25:26 2014
@@ -0,0 +1,130 @@
+/*
+ *
+ * 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.qpid.server.security.encryption;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+
+class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
+{
+    private static final String CIPHER_NAME = "AES/CBC/PKCS5Padding";
+    private static final int AES_INITIALIZATION_VECTOR_LENGTH = 16;
+    private final SecretKey _secretKey;
+    private final SecureRandom _random = new SecureRandom();
+
+    AESKeyFileEncrypter(SecretKey secretKey)
+    {
+        _secretKey = secretKey;
+    }
+
+    @Override
+    public String encrypt(final String unencrypted)
+    {
+        byte[] unencryptedBytes = unencrypted.getBytes(StandardCharsets.UTF_8);
+        try
+        {
+            byte[] ivbytes = new byte[AES_INITIALIZATION_VECTOR_LENGTH];
+            _random.nextBytes(ivbytes);
+            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
+            cipher.init(Cipher.ENCRYPT_MODE, _secretKey, new IvParameterSpec(ivbytes));
+            byte[] encryptedBytes = readFromCipherStream(unencryptedBytes, cipher);
+            byte[] output = new byte[AES_INITIALIZATION_VECTOR_LENGTH + encryptedBytes.length];
+            System.arraycopy(ivbytes, 0, output, 0, AES_INITIALIZATION_VECTOR_LENGTH);
+            System.arraycopy(encryptedBytes, 0, output, AES_INITIALIZATION_VECTOR_LENGTH,
encryptedBytes.length);
+            return DatatypeConverter.printBase64Binary(output);
+        }
+        catch (IOException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException
| NoSuchPaddingException e)
+        {
+            throw new IllegalConfigurationException("Unable to encrypt secret", e);
+        }
+    }
+
+    @Override
+    public String decrypt(final String encrypted)
+    {
+        byte[] encryptedBytes = DatatypeConverter.parseBase64Binary(encrypted);
+        try
+        {
+            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
+            cipher.init(Cipher.DECRYPT_MODE, _secretKey, new IvParameterSpec(encryptedBytes,
0,
+                                                                             AES_INITIALIZATION_VECTOR_LENGTH));
+            return new String(readFromCipherStream(encryptedBytes,
+                                                   AES_INITIALIZATION_VECTOR_LENGTH,
+                                                   encryptedBytes.length - AES_INITIALIZATION_VECTOR_LENGTH,
+                                                   cipher), StandardCharsets.UTF_8);
+        }
+        catch (IOException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException
| NoSuchPaddingException e)
+        {
+            throw new IllegalConfigurationException("Unable to encrypt secret", e);
+        }
+    }
+
+
+    private byte[] readFromCipherStream(final byte[] unencryptedBytes, final Cipher cipher)
throws IOException
+    {
+        return readFromCipherStream(unencryptedBytes, 0, unencryptedBytes.length, cipher);
+    }
+
+    private byte[] readFromCipherStream(final byte[] unencryptedBytes, int offset, int length,
final Cipher cipher)
+            throws IOException
+    {
+        final byte[] encryptedBytes;
+        try (CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(unencryptedBytes,
+                                                                                        
         offset,
+                                                                                        
         length), cipher))
+        {
+            byte[] buf = new byte[1024];
+            int pos = 0;
+            int read;
+            while ((read = cipherInputStream.read(buf, pos, buf.length - pos)) != -1)
+            {
+                pos += read;
+                if (pos == buf.length - 1)
+                {
+                    byte[] tmp = buf;
+                    buf = new byte[buf.length + 1024];
+                    System.arraycopy(tmp, 0, buf, 0, tmp.length);
+                }
+            }
+            encryptedBytes = new byte[pos];
+            System.arraycopy(buf, 0, encryptedBytes, 0, pos);
+        }
+        return encryptedBytes;
+    }
+
+
+
+}

Added: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java?rev=1618815&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
(added)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
Tue Aug 19 07:25:26 2014
@@ -0,0 +1,164 @@
+/*
+ *
+ * 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.qpid.server.security.encryption;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.security.NoSuchAlgorithmException;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.qpid.server.BrokerOptions;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterFactory
+{
+    private static final String ENCRYPTER_KEY_FILE = "encrypter.key.file";
+
+    private static final int AES_KEY_SIZE_BITS = 256;
+    private static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
+    private static final String AES_ALGORITHM = "AES";
+
+    public static String TYPE = "AESKeyFile";
+
+    @Override
+    public ConfigurationSecretEncrypter createEncrypter(final ConfiguredObject<?> object)
+    {
+        String fileLocation;
+        if(object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
+        {
+            fileLocation = object.getContextValue(String.class, ENCRYPTER_KEY_FILE);
+        }
+        else
+        {
+
+            fileLocation = object.getContextValue(String.class, BrokerOptions.QPID_WORK_DIR)
+                           + File.separator + ".keys" + File.separator
+                           + object.getCategoryClass().getSimpleName() + "_"
+                           + object.getName() + ".key";
+
+            Map<String, String> context = object.getContext();
+            Map<String, String> modifiedContext = new LinkedHashMap<>(context);
+            modifiedContext.put(ENCRYPTER_KEY_FILE, fileLocation);
+
+            object.setAttribute(ConfiguredObject.CONTEXT, context, modifiedContext);
+        }
+        File file = new File(fileLocation);
+        if(!file.exists())
+        {
+            createAndPopulateKeyFile(file);
+        }
+        if(!file.isFile())
+        {
+            throw new IllegalArgumentException("File '"+fileLocation+"' is not a regular
file.");
+        }
+        try
+        {
+            Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());
+
+            if (permissions.contains(PosixFilePermission.GROUP_READ)
+                || permissions.contains(PosixFilePermission.OTHERS_READ)
+                || permissions.contains(PosixFilePermission.GROUP_WRITE)
+                || permissions.contains(PosixFilePermission.OTHERS_WRITE))
+            {
+                throw new IllegalStateException("Key file '"
+                                                + fileLocation
+                                                + "' has incorrect permissions.  Only the
owner "
+                                                + "should be able to read or write this file.");
+            }
+            if(Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
+            {
+                throw new IllegalConfigurationException("Key file '" + fileLocation + "'
contains an incorrect about of data");
+            }
+
+            try(FileInputStream inputStream = new FileInputStream(file))
+            {
+                byte[] key = new byte[AES_KEY_SIZE_BYTES];
+                int pos = 0;
+                int read;
+                while(pos < key.length && -1 != ( read = inputStream.read(key,
pos, key.length - pos)))
+                {
+                    pos += read;
+                }
+                if(pos != key.length)
+                {
+                    throw new IllegalConfigurationException("Key file '" + fileLocation +
"' contained an incorrect about of data");
+                }
+                SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
+                return new AESKeyFileEncrypter(keySpec);
+            }
+        }
+        catch (IOException e)
+        {
+            throw new IllegalConfigurationException("Unable to get file permissions: " +
e.getMessage(), e);
+        }
+    }
+
+    private void createAndPopulateKeyFile(final File file)
+    {
+        try
+        {
+            Set<PosixFilePermission> ownerOnly = EnumSet.of(PosixFilePermission.OWNER_READ,
+                                                            PosixFilePermission.OWNER_WRITE,
+                                                            PosixFilePermission.OWNER_EXECUTE);
+            Files.createDirectories(file.getParentFile().toPath(), PosixFilePermissions.asFileAttribute(ownerOnly));
+
+            Files.createFile(file.toPath(), PosixFilePermissions.asFileAttribute(
+                    EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)));
+
+            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
+            keyGenerator.init(AES_KEY_SIZE_BITS);
+            SecretKey key = keyGenerator.generateKey();
+            try(FileOutputStream os = new FileOutputStream(file))
+            {
+                os.write(key.getEncoded());
+            }
+
+            Files.setPosixFilePermissions(file.toPath(), EnumSet.of(PosixFilePermission.OWNER_READ));
+        }
+        catch (NoSuchAlgorithmException | IOException e)
+        {
+            throw new IllegalConfigurationException("Cannot create key file: " + e.getMessage(),
e);
+        }
+
+    }
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+}

Added: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/ConfigurationSecretEncrypter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/ConfigurationSecretEncrypter.java?rev=1618815&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/ConfigurationSecretEncrypter.java
(added)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/encryption/ConfigurationSecretEncrypter.java
Tue Aug 19 07:25:26 2014
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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.qpid.server.security.encryption;
+
+public interface ConfigurationSecretEncrypter
+{
+    String encrypt(String unencrypted);
+
+    String decrypt(String encrypted);
+}

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/GenericRecoverer.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/GenericRecoverer.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/GenericRecoverer.java
(original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/GenericRecoverer.java
Tue Aug 19 07:25:26 2014
@@ -170,6 +170,7 @@ public class GenericRecoverer
                     {
                         updatesMade = true;
                         ConfiguredObject<?> resolved = recovered.resolve();
+                        resolved.decryptSecrets();
                         resolvedObjects.put(resolved.getId(), resolved);
                     }
                     else

Modified: qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
(original)
+++ qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
Tue Aug 19 07:25:26 2014
@@ -65,6 +65,7 @@ public class BrokerRestHttpsTest extends
 
         Asserts.assertAttributesPresent(brokerDetails, BrokerModel.getInstance().getTypeRegistry().getAttributeNames(Broker.class),
                 Broker.PROCESS_PID,
+                Broker.CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER,
                 ConfiguredObject.TYPE,
                 ConfiguredObject.CREATED_BY,
                 ConfiguredObject.CREATED_TIME,

Modified: qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java?rev=1618815&r1=1618814&r2=1618815&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
(original)
+++ qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/BrokerRestTest.java
Tue Aug 19 07:25:26 2014
@@ -204,6 +204,7 @@ public class BrokerRestTest extends Qpid
         Asserts.assertAttributesPresent(brokerDetails, BrokerModel.getInstance().getTypeRegistry().getAttributeNames(
                 Broker.class),
                 Broker.PROCESS_PID,
+                Broker.CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER,
                 ConfiguredObject.TYPE,
                 ConfiguredObject.CREATED_BY,
                 ConfiguredObject.CREATED_TIME,



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message