Skip to content

Commit

Permalink
KNOX-1162 - Logging stacktrace for FATAL messages and displaying a me…
Browse files Browse the repository at this point in the history
…aningful error message in case of missing/non-parsable JAAS configuration (#55)
  • Loading branch information
smolnar82 authored and risdenk committed Feb 19, 2019
1 parent c5d4111 commit dac2f2e
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 8 deletions.
Expand Up @@ -34,13 +34,13 @@
public interface GatewayMessages {

@Message( level = MessageLevel.FATAL, text = "Failed to parse command line: {0}" )
void failedToParseCommandLine( @StackTrace( level = MessageLevel.DEBUG ) ParseException e );
void failedToParseCommandLine( @StackTrace( level = MessageLevel.FATAL ) ParseException e );

@Message( level = MessageLevel.INFO, text = "Starting gateway..." )
void startingGateway();

@Message( level = MessageLevel.FATAL, text = "Failed to start gateway: {0}" )
void failedToStartGateway( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
void failedToStartGateway( @StackTrace( level = MessageLevel.FATAL ) Exception e );

@Message( level = MessageLevel.INFO, text = "Started gateway on port {0}." )
void startedGateway( int port );
Expand Down Expand Up @@ -227,7 +227,7 @@ public interface GatewayMessages {
void failedToReloadTopologies( @StackTrace( level = MessageLevel.DEBUG ) Exception e );

@Message( level = MessageLevel.FATAL, text = "Unsupported encoding: {0}" )
void unsupportedEncoding( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
void unsupportedEncoding( @StackTrace( level = MessageLevel.FATAL ) Exception e );

@Message( level = MessageLevel.ERROR, text = "Failed to persist master secret: {0}" )
void failedToPersistMasterSecret( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
Expand Down
4 changes: 4 additions & 0 deletions gateway-service-remoteconfig/pom.xml
Expand Up @@ -38,6 +38,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
<artifactId>gateway-util-configinjector</artifactId>
</dependency>

<dependency>
<groupId>org.apache.zookeeper</groupId>
Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.knox.gateway.config.ConfigurationException;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.service.config.remote.RemoteConfigurationMessages;
Expand Down Expand Up @@ -73,8 +74,12 @@ public void init(GatewayConfig config, Map<String, String> options) throws Servi
// Load the remote registry configurations
List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>(RemoteConfigurationRegistriesAccessor.getRemoteRegistryConfigurations(config));

// Configure registry authentication
// Configure registry authentication
try {
RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, aliasService);
} catch (ConfigurationException e) {
throw new ServiceLifecycleException("Error while configuring registry authentication", e);
}

if (registryConfigs.size() > 1) {
// Warn about current limit on number of supported client configurations
Expand Down
Expand Up @@ -16,6 +16,8 @@
*/
package org.apache.knox.gateway.service.config.remote.zk;

import org.apache.knox.gateway.config.ConfigurationException;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.service.config.remote.RemoteConfigurationMessages;
import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
Expand All @@ -34,6 +36,8 @@
*/
class RemoteConfigurationRegistryJAASConfig extends Configuration {

static final String JAAS_CONFIG_ERRROR_PREFIX = "Error while getting secure configuration. This error usually indicates an issue within the supplied JAAS configuration";

// Underlying SASL mechanisms supported
enum SASLMechanism {
Unsupported,
Expand All @@ -49,17 +53,25 @@ enum SASLMechanism {
private static final RemoteConfigurationMessages log = MessagesFactory.get(RemoteConfigurationMessages.class);

// Cache the current JAAS configuration
private Configuration delegate = Configuration.getConfiguration();
private final Configuration delegate;

private AliasService aliasService;
private final AliasService aliasService;

private Map<String, AppConfigurationEntry[]> contextEntries = new HashMap<>();
private final Map<String, AppConfigurationEntry[]> contextEntries = new HashMap<>();

static RemoteConfigurationRegistryJAASConfig configure(List<RemoteConfigurationRegistryConfig> configs, AliasService aliasService) {
return new RemoteConfigurationRegistryJAASConfig(configs, aliasService);
}

private RemoteConfigurationRegistryJAASConfig(List<RemoteConfigurationRegistryConfig> configs, AliasService aliasService) {
try {
delegate = Configuration.getConfiguration();
} catch(Exception e) {
//populate the original error with a meaningful message; logging will happen later in the call hierarchy
final String message = String.format(Locale.ROOT, "%s: %s", JAAS_CONFIG_ERRROR_PREFIX, System.getProperty(GatewayConfig.KRB5_LOGIN_CONFIG, "Undefined"));
throw new ConfigurationException(message, e);
}

this.aliasService = aliasService;

// Populate context entries
Expand Down Expand Up @@ -135,6 +147,8 @@ private AppConfigurationEntry createEntry(RemoteConfigurationRegistryConfig conf
opts.put("isUseKeyTab", String.valueOf(config.isUseKeyTab()));
opts.put("keyTab", config.getKeytab());
opts.put("principal", config.getPrincipal());
default:
break;
}

if (!opts.isEmpty()) {
Expand All @@ -159,6 +173,8 @@ private static String getLoginModuleName(String registryType, SASLMechanism sasl
break;
case Digest:
loginModuleName = digestLoginModules.get(registryType.toUpperCase(Locale.ROOT));
default:
break;
}
return loginModuleName;
}
Expand Down
Expand Up @@ -16,14 +16,25 @@
*/
package org.apache.knox.gateway.service.config.remote.zk;

import org.apache.commons.io.FileUtils;
import org.apache.knox.gateway.config.ConfigurationException;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
import org.apache.knox.gateway.services.security.AliasService;
import org.easymock.EasyMock;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;

import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;

import static org.hamcrest.CoreMatchers.startsWith;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -36,6 +47,12 @@

public class RemoteConfigurationRegistryJAASConfigTest {

@Rule
public final TemporaryFolder testFolder = new TemporaryFolder();

@Rule
public final ExpectedException expectedException = ExpectedException.none();

@Test
public void testZooKeeperDigestContextEntry() throws Exception {
List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>();
Expand Down Expand Up @@ -166,6 +183,54 @@ public void testZooKeeperDigestContextEntryWithoutAliasService() throws Exceptio
}
}

@Test
public void shouldRaiseAnErrorWithMeaningfulErrorMessageIfAuthLoginConfigCannotBeRead() throws Exception {
final List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>();
System.setProperty(GatewayConfig.KRB5_LOGIN_CONFIG, "nonExistingFilePath");

expectedException.expect(ConfigurationException.class);
expectedException.expectMessage(startsWith(RemoteConfigurationRegistryJAASConfig.JAAS_CONFIG_ERRROR_PREFIX));

try {
RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, null);
} finally {
System.clearProperty(GatewayConfig.KRB5_LOGIN_CONFIG);
}
}

@Test
public void shouldRaiseAnErrorWithMeaningfulErrorMessageIfAuthLoginConfigCannotBeParsed() throws Exception {
final List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>();
final String jaasConfigFilePath = writeInvalidJaasConf();
System.setProperty(GatewayConfig.KRB5_LOGIN_CONFIG, jaasConfigFilePath);

expectedException.expect(ConfigurationException.class);
expectedException.expectMessage(startsWith(RemoteConfigurationRegistryJAASConfig.JAAS_CONFIG_ERRROR_PREFIX));

try {
RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, null);
} finally {
System.clearProperty(GatewayConfig.KRB5_LOGIN_CONFIG);
}
}

private String writeInvalidJaasConf() throws IOException {
final File jaasConfigFile = testFolder.newFile("jaas.conf");
final String jaasConfig = "com.sun.security.jgss.initiate {" +
"com.sun.security.auth.module.Krb5LoginModule required" +
"renewTGT=false" +
"doNotPrompt=true" +
"useKeyTab=true" +
"keyTab=/etc/security/keytabs/knox.service.keytab" + //note the missing quotes; it should be keyTab="/etc/security/keytabs/knox.service.keytab"
"principal=\"knox/myHost@myRealm\"" +
"storeKey=true" +
"useTicketCache=false; " +
"};";

FileUtils.writeStringToFile(jaasConfigFile, jaasConfig, StandardCharsets.UTF_8);
return jaasConfigFile.getAbsolutePath();
}

private static RemoteConfigurationRegistryConfig createDigestConfig(String entryName,
String principal,
String credentialAlias) {
Expand Down
Expand Up @@ -796,7 +796,7 @@ public void testMultipleDoubleStarPathMatching() throws URISyntaxException {
Template template;
Template input;
Matcher<String> stringMatcher;
Matcher<?>.Match match;
Matcher<String>.Match match;

// template = Parser.parse( "*://*:*/**/webhdfs/v1/**?**" );
// input = Parser.parse( "http://localhost:53221/gateway/cluster/webhdfs/v1/tmp/GatewayWebHdfsFuncTest/testBasicHdfsUseCase/dir?user.name=hdfs&op=MKDIRS" );
Expand Down

0 comments on commit dac2f2e

Please sign in to comment.