Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WFCORE-114] : Get RuntimeVaultReader into WildFly Core #679

Merged
merged 2 commits into from
May 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@
<module name="org.jboss.as.protocol"/>
<module name="org.jboss.as.remoting"/>
<module name="org.wildfly.security.manager" services="import"/>
<module name="org.jboss.as.security" optional="true" services="import"/>
<module name="org.jboss.as.server"/>
<module name="org.jboss.as.server" services="import"/>
<module name="org.jboss.as.version"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.logmanager" services="import"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
<module name="org.jboss.as.remoting"/>
<module name="org.jboss.as.self-contained" optional="true"/>
<module name="org.wildfly.security.manager" services="import"/>
<module name="org.jboss.as.security" optional="true" services="import"/>
<module name="org.jboss.as.version"/>
<module name="org.picketbox" optional="true"/>
<module name="io.undertow.core" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -110,6 +111,7 @@
import org.jboss.as.domain.controller.HostRegistrations;
import org.jboss.as.domain.controller.LocalHostControllerInfo;
import org.jboss.as.domain.controller.SlaveRegistrationException;
import org.jboss.as.domain.controller.logging.DomainControllerLogger;
import org.jboss.as.domain.controller.operations.ApplyMissingDomainModelResourcesHandler;
import org.jboss.as.domain.controller.operations.coordination.PrepareStepHandler;
import org.jboss.as.domain.controller.resources.DomainRootDefinition;
Expand Down Expand Up @@ -223,7 +225,7 @@ static ServiceController<ModelController> addService(final ServiceTarget service
final ConcurrentMap<String, ProxyController> hostProxies = new ConcurrentHashMap<String, ProxyController>();
final Map<String, ProxyController> serverProxies = new ConcurrentHashMap<String, ProxyController>();
final LocalHostControllerInfoImpl hostControllerInfo = new LocalHostControllerInfoImpl(processState, environment);
final AbstractVaultReader vaultReader = service(AbstractVaultReader.class);
final AbstractVaultReader vaultReader = loadVaultReaderService();
ROOT_LOGGER.debugf("Using VaultReader %s", vaultReader);
final ContentRepository contentRepository = ContentRepository.Factory.create(environment.getDomainContentDir());
final IgnoredDomainResourceRegistry ignoredRegistry = new IgnoredDomainResourceRegistry(hostControllerInfo);
Expand Down Expand Up @@ -1080,11 +1082,24 @@ public boolean awaitServerSuspend(Set<String> waitForServers, int timeout) {
}
}

private static <S> S service(final Class<S> service) {
final ServiceLoader<S> serviceLoader = ServiceLoader.load(service);
final Iterator<S> it = serviceLoader.iterator();
if (it.hasNext())
return it.next();
private static AbstractVaultReader loadVaultReaderService() {
final ServiceLoader<AbstractVaultReader> serviceLoader = ServiceLoader.load(AbstractVaultReader.class,
DomainModelControllerService.class.getClassLoader());
final Iterator<AbstractVaultReader> it = serviceLoader.iterator();
// TODO WFCORE-114 get rid of catching/suppressing errors once we have a complete impl in WFCORE
ServiceConfigurationError sce = null;
while (it.hasNext()) {
try {
return it.next();
} catch (ServiceConfigurationError e) {
if (sce == null) {
sce = e;
}
}
}
if (sce != null) {
DomainControllerLogger.HOST_CONTROLLER_LOGGER.debugf(sce, "Cannot instantiate provider of service %s", AbstractVaultReader.class);
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.TreeSet;

Expand Down Expand Up @@ -150,7 +151,7 @@ public synchronized void start(final StartContext context) throws StartException
ServiceModuleLoader.addService(serviceTarget, configuration);
ExternalModuleService.addService(serviceTarget);
ModuleIndexService.addService(serviceTarget);
final AbstractVaultReader vaultReader = service(AbstractVaultReader.class);
final AbstractVaultReader vaultReader = loadVaultReaderService();
ServerLogger.AS_ROOT_LOGGER.debugf("Using VaultReader %s", vaultReader);
ServerService.addService(serviceTarget, configuration, processState, bootstrapListener, runningModeControl, vaultReader, configuration.getAuditLogger(), configuration.getAuthorizer());
final ServiceActivatorContext serviceActivatorContext = new ServiceActivatorContext() {
Expand Down Expand Up @@ -217,11 +218,24 @@ private String getVMArguments() {
return result.toString();
}

private static <S> S service(final Class<S> service) {
final ServiceLoader<S> serviceLoader = ServiceLoader.load(service);
final Iterator<S> it = serviceLoader.iterator();
if (it.hasNext())
return it.next();
private static AbstractVaultReader loadVaultReaderService() {
final ServiceLoader<AbstractVaultReader> serviceLoader = ServiceLoader.load(AbstractVaultReader.class,
ApplicationServerService.class.getClassLoader());
final Iterator<AbstractVaultReader> it = serviceLoader.iterator();
// TODO WFCORE-114 get rid of catching/suppressing errors once we have a complete impl in WFCORE
ServiceConfigurationError sce = null;
while (it.hasNext()) {
try {
return it.next();
} catch (ServiceConfigurationError e) {
if (sce == null) {
sce = e;
}
}
}
if (sce != null) {
ServerLogger.AS_ROOT_LOGGER.debugf(sce, "Cannot instantiate provider of service %s", AbstractVaultReader.class);
}
return null;
}
}
38 changes: 38 additions & 0 deletions server/src/main/java/org/jboss/as/server/logging/ServerLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -1115,4 +1115,42 @@ OperationFailedException illegalCombinationOfHttpManagementInterfaceConfiguratio
@Message(id = 225, value="Unable to create temporary directory")
RuntimeException unableToCreateSelfContainedDir();

/**
* Creates a {@link RuntimeException}
* @param e the underlying exception
* @return
*/
@Message(id = 226, value = "Runtime Exception:")
RuntimeException runtimeException(@Cause Throwable e);

/**
* Create a {@link org.jboss.as.server.services.security.VaultReaderException} to indicate there was an exception while reading from the vault
* @param t underlying exception
* @return {@link org.jboss.as.server.services.security.VaultReaderException}
*/
@Message(id = 227, value = "Vault Reader Exception:")
VaultReaderException vaultReaderException(@Cause Throwable t);

/**
* Create a {@link SecurityException}
* @param t underlying exception
* @return {@link SecurityException}
*/
@Message(id = 228, value = "Security Exception")
SecurityException securityException(@Cause Throwable t);

/**
* Create a {@link SecurityException}
* @param msg message that is passed in creating the exception
* @return {@link SecurityException}
*/
@Message(id = 229, value = "Security Exception: %s")
SecurityException securityException(String msg);

/**
* Create a {@link SecurityException} to indicate that the vault is not initialized
* @return {@link SecurityException}
*/
@Message(id = 230, value = "Vault is not initialized")
SecurityException vaultNotInitializedException();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.server.services.security;

import static java.security.AccessController.doPrivileged;

import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.jboss.as.server.logging.ServerLogger;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
import org.jboss.modules.ModuleLoader;
import org.jboss.security.vault.SecurityVault;
import org.jboss.security.vault.SecurityVaultException;
import org.jboss.security.vault.SecurityVaultFactory;
import org.wildfly.security.manager.WildFlySecurityManager;
import org.wildfly.security.manager.action.GetModuleClassLoaderAction;

/**
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
*/
public class RuntimeVaultReader extends AbstractVaultReader {

private static final Pattern VAULT_PATTERN = Pattern.compile("VAULT::.*::.*::.*");

private volatile SecurityVault vault;


/**
* This constructor should remain protected to keep the vault as invisible
* as possible, but it needs to be exposed for service plug-ability.
*/
public RuntimeVaultReader() {
}

protected void createVault(final String fqn, final Map<String, Object> options) throws VaultReaderException {
createVault(fqn, null, options);
}

protected void createVault(final String fqn, final String module, final Map<String, Object> options) throws VaultReaderException {
Map<String, Object> vaultOptions = new HashMap<String, Object>(options);
SecurityVault vault = null;
try {
vault = AccessController.doPrivileged(new PrivilegedExceptionAction<SecurityVault>() {
@Override
public SecurityVault run() throws Exception {
if (fqn == null || fqn.isEmpty()) {
return SecurityVaultFactory.get();
} else if (module == null ){
return SecurityVaultFactory.get(fqn);
} else {
return SecurityVaultFactory.get(getModuleClassLoader(module), fqn);
}
}
});
} catch (PrivilegedActionException e) {
Throwable t = e.getCause();
if (t instanceof SecurityVaultException) {
throw ServerLogger.ROOT_LOGGER.vaultReaderException(t);
}
if (t instanceof RuntimeException) {
throw ServerLogger.ROOT_LOGGER.runtimeException(t);
}
throw ServerLogger.ROOT_LOGGER.runtimeException(t);
}
try {
vault.init(vaultOptions);
} catch (SecurityVaultException e) {
throw ServerLogger.ROOT_LOGGER.vaultReaderException(e);
}
this.vault = vault;
}

protected void destroyVault() {
//TODO - there are no cleanup methods in the vault itself
vault = null;
}

public String retrieveFromVault(final String password) throws SecurityException {
if (isVaultFormat(password)) {

if (vault == null) {
throw ServerLogger.ROOT_LOGGER.vaultNotInitializedException();
}

try {
return getValueAsString(password);
} catch (SecurityVaultException e) {
throw ServerLogger.ROOT_LOGGER.securityException(e);
}

}
return password;
}

private String getValueAsString(String vaultString) throws SecurityVaultException {
char[] val = getValue(vaultString);
if (val != null) {
return new String(val);
}
return null;
}

@Override
public boolean isVaultFormat(String str) {
return str != null && VAULT_PATTERN.matcher(str).matches();
}

private char[] getValue(String vaultString) throws SecurityVaultException {
String[] tokens = tokens(vaultString);
byte[] sharedKey = null;
if (tokens.length > 2) {
// only in case of conversion of old vault implementation
sharedKey = tokens[3].getBytes(StandardCharsets.UTF_8);
}

return vault.retrieve(tokens[1], tokens[2], sharedKey);
}

private String[] tokens(String vaultString) {
StringTokenizer tokenizer = new StringTokenizer(vaultString, "::");
int length = tokenizer.countTokens();
String[] tokens = new String[length];

int index = 0;
while (tokenizer.hasMoreTokens()) {
tokens[index++] = tokenizer.nextToken();
}
return tokens;
}

private ModuleClassLoader getModuleClassLoader(final String moduleSpec) throws ModuleLoadException {
ModuleLoader loader = Module.getCallerModuleLoader();
final Module module = loader.loadModule(ModuleIdentifier.fromString(moduleSpec));
return WildFlySecurityManager.isChecking() ? doPrivileged(new GetModuleClassLoaderAction(module)) : module.getClassLoader();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.jboss.as.server.services.security.RuntimeVaultReader