You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2018/01/11 17:39:11 UTC
[44/53] [abbrv] knox git commit: KNOX-998 - Merge from trunk 0.14.0
code
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/config/RemoteConfigurationRegistry.java b/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
deleted file mode 100644
index f3e7dbd..0000000
--- a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.hadoop.gateway.service.config.remote.config;
-
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
-
-import javax.xml.bind.annotation.XmlElement;
-
-class RemoteConfigurationRegistry implements RemoteConfigurationRegistryConfig {
-
- private String name;
- private String type;
- private String connectionString;
- private String namespace;
- private String authType;
- private String principal;
- private String credentialAlias;
- private String keyTab;
- private boolean useKeyTab;
- private boolean useTicketCache;
-
- RemoteConfigurationRegistry() {
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public void setRegistryType(String type) {
- this.type = type;
- }
-
- public void setConnectionString(String connectionString) {
- this.connectionString = connectionString;
- }
-
- public void setNamespace(String namespace) {
- this.namespace = namespace;
- }
-
- public void setAuthType(String authType) {
- this.authType = authType;
- }
-
- public void setPrincipal(String principal) {
- this.principal = principal;
- }
-
- public void setCredentialAlias(String alias) {
- this.credentialAlias = alias;
- }
-
- public void setUseTicketCache(boolean useTicketCache) {
- this.useTicketCache = useTicketCache;
- }
-
- public void setUseKeytab(boolean useKeytab) {
- this.useKeyTab = useKeytab;
- }
-
- public void setKeytab(String keytab) {
- this.keyTab = keytab;
- }
-
- @XmlElement(name="name")
- public String getName() {
- return name;
- }
-
- @XmlElement(name="type")
- public String getRegistryType() {
- return type;
- }
-
- @XmlElement(name="auth-type")
- public String getAuthType() {
- return authType;
- }
-
- @XmlElement(name="principal")
- public String getPrincipal() {
- return principal;
- }
-
- @XmlElement(name="credential-alias")
- public String getCredentialAlias() {
- return credentialAlias;
- }
-
- @Override
- @XmlElement(name="address")
- public String getConnectionString() {
- return connectionString;
- }
-
- @Override
- @XmlElement(name="namespace")
- public String getNamespace() {
- return namespace;
- }
-
- @Override
- @XmlElement(name="use-ticket-cache")
- public boolean isUseTicketCache() {
- return useTicketCache;
- }
-
- @Override
- @XmlElement(name="use-key-tab")
- public boolean isUseKeyTab() {
- return useKeyTab;
- }
-
- @Override
- @XmlElement(name="keytab")
- public String getKeytab() {
- return keyTab;
- }
-
- @Override
- public boolean isSecureRegistry() {
- return (getAuthType() != null);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/CuratorClientService.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/CuratorClientService.java b/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/CuratorClientService.java
deleted file mode 100644
index f9b5ab3..0000000
--- a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/CuratorClientService.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.hadoop.gateway.service.config.remote.zk;
-
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.framework.api.ACLProvider;
-import org.apache.curator.framework.imps.DefaultACLProvider;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.NodeCache;
-import org.apache.curator.framework.recipes.cache.NodeCacheListener;
-import org.apache.curator.framework.recipes.cache.PathChildrenCache;
-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.hadoop.gateway.config.GatewayConfig;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationMessages;
-import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClient.ChildEntryListener;
-import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClient.EntryListener;
-import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClient;
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
-import org.apache.hadoop.gateway.service.config.remote.config.RemoteConfigurationRegistriesAccessor;
-import org.apache.hadoop.gateway.services.ServiceLifecycleException;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.client.ZooKeeperSaslClient;
-import org.apache.zookeeper.data.ACL;
-import org.apache.zookeeper.data.Id;
-import org.apache.zookeeper.data.Stat;
-
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * RemoteConfigurationRegistryClientService implementation that employs the Curator ZooKeeper client framework.
- */
-class CuratorClientService implements ZooKeeperClientService {
-
- private static final String LOGIN_CONTEXT_NAME_PROPERTY = ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY;
-
- private static final String DEFAULT_LOGIN_CONTEXT_NAME = "Client";
-
- private static final RemoteConfigurationMessages log =
- MessagesFactory.get(RemoteConfigurationMessages.class);
-
- private Map<String, RemoteConfigurationRegistryClient> clients = new HashMap<>();
-
- private AliasService aliasService = null;
-
-
- @Override
- public void init(GatewayConfig config, Map<String, String> options) throws ServiceLifecycleException {
-
- List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>();
-
- // Load the remote registry configurations
- registryConfigs.addAll(RemoteConfigurationRegistriesAccessor.getRemoteRegistryConfigurations(config));
-
- // Configure registry authentication
- RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, aliasService);
-
- if (registryConfigs.size() > 1) {
- // Warn about current limit on number of supported client configurations
- log.multipleRemoteRegistryConfigurations();
- }
-
- // Create the clients
- for (RemoteConfigurationRegistryConfig registryConfig : registryConfigs) {
- if (TYPE.equalsIgnoreCase(registryConfig.getRegistryType())) {
- RemoteConfigurationRegistryClient registryClient = createClient(registryConfig);
- clients.put(registryConfig.getName(), registryClient);
- }
- }
- }
-
- @Override
- public void setAliasService(AliasService aliasService) {
- this.aliasService = aliasService;
- }
-
- @Override
- public void start() throws ServiceLifecycleException {
- }
-
- @Override
- public void stop() throws ServiceLifecycleException {
- }
-
- @Override
- public RemoteConfigurationRegistryClient get(String name) {
- return clients.get(name);
- }
-
-
- private RemoteConfigurationRegistryClient createClient(RemoteConfigurationRegistryConfig config) {
- ACLProvider aclProvider;
- if (config.isSecureRegistry()) {
- configureSasl(config);
- aclProvider = new SASLOwnerACLProvider();
- } else {
- // Clear SASL system property
- System.clearProperty(LOGIN_CONTEXT_NAME_PROPERTY);
- aclProvider = new DefaultACLProvider();
- }
-
- CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString(config.getConnectionString())
- .retryPolicy(new ExponentialBackoffRetry(1000, 3))
- .aclProvider(aclProvider)
- .build();
- client.start();
-
- return (new ClientAdapter(client, config));
- }
-
-
- private void configureSasl(RemoteConfigurationRegistryConfig config) {
- String registryName = config.getName();
- if (registryName == null) {
- registryName = DEFAULT_LOGIN_CONTEXT_NAME;
- }
- System.setProperty(LOGIN_CONTEXT_NAME_PROPERTY, registryName);
- }
-
-
- private static final class ClientAdapter implements RemoteConfigurationRegistryClient {
-
- private static final String DEFAULT_ENCODING = "UTF-8";
-
- private CuratorFramework delegate;
-
- private RemoteConfigurationRegistryConfig config;
-
- private Map<String, NodeCache> entryNodeCaches = new HashMap<>();
-
- ClientAdapter(CuratorFramework delegate, RemoteConfigurationRegistryConfig config) {
- this.delegate = delegate;
- this.config = config;
- }
-
- @Override
- public String getAddress() {
- return config.getConnectionString();
- }
-
- @Override
- public boolean isAuthenticationConfigured() {
- return config.isSecureRegistry();
- }
-
- @Override
- public boolean entryExists(String path) {
- Stat s = null;
- try {
- s = delegate.checkExists().forPath(path);
- } catch (Exception e) {
- // Ignore
- }
- return (s != null);
- }
-
- @Override
- public List<RemoteConfigurationRegistryClient.EntryACL> getACL(String path) {
- List<RemoteConfigurationRegistryClient.EntryACL> acl = new ArrayList<>();
- try {
- List<ACL> zkACL = delegate.getACL().forPath(path);
- if (zkACL != null) {
- for (ACL aclEntry : zkACL) {
- RemoteConfigurationRegistryClient.EntryACL entryACL = new ZooKeeperACLAdapter(aclEntry);
- acl.add(entryACL);
- }
- }
- } catch (Exception e) {
- log.errorHandlingRemoteConfigACL(path, e);
- }
- return acl;
- }
-
- @Override
- public void setACL(String path, List<EntryACL> entryACLs) {
- // Translate the abstract ACLs into ZooKeeper ACLs
- List<ACL> delegateACLs = new ArrayList<>();
- for (EntryACL entryACL : entryACLs) {
- String scheme = entryACL.getType();
- String id = entryACL.getId();
- int permissions = 0;
- if (entryACL.canWrite()) {
- permissions = ZooDefs.Perms.ALL;
- } else if (entryACL.canRead()){
- permissions = ZooDefs.Perms.READ;
- }
- delegateACLs.add(new ACL(permissions, new Id(scheme, id)));
- }
-
- try {
- // Set the ACLs for the path
- delegate.setACL().withACL(delegateACLs).forPath(path);
- } catch (Exception e) {
- log.errorSettingEntryACL(path, e);
- }
- }
-
- @Override
- public List<String> listChildEntries(String path) {
- List<String> result = null;
- try {
- result = delegate.getChildren().forPath(path);
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- return result;
- }
-
- @Override
- public void addChildEntryListener(String path, ChildEntryListener listener) throws Exception {
- PathChildrenCache childCache = new PathChildrenCache(delegate, path, false);
- childCache.getListenable().addListener(new ChildEntryListenerAdapter(this, listener));
- childCache.start();
- }
-
- @Override
- public void addEntryListener(String path, EntryListener listener) throws Exception {
- NodeCache nodeCache = new NodeCache(delegate, path);
- nodeCache.getListenable().addListener(new EntryListenerAdapter(this, nodeCache, listener));
- nodeCache.start();
- entryNodeCaches.put(path, nodeCache);
- }
-
- @Override
- public void removeEntryListener(String path) throws Exception {
- NodeCache nodeCache = entryNodeCaches.remove(path);
- if (nodeCache != null) {
- nodeCache.close();
- }
- }
-
- @Override
- public String getEntryData(String path) {
- return getEntryData(path, DEFAULT_ENCODING);
- }
-
- @Override
- public String getEntryData(String path, String encoding) {
- String result = null;
- try {
- byte[] data = delegate.getData().forPath(path);
- if (data != null) {
- result = new String(data, Charset.forName(encoding));
- }
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- return result;
- }
-
- @Override
- public void createEntry(String path) {
- try {
- if (delegate.checkExists().forPath(path) == null) {
- delegate.create().forPath(path);
- }
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- }
-
- @Override
- public void createEntry(String path, String data) {
- createEntry(path, data, DEFAULT_ENCODING);
- }
-
- @Override
- public void createEntry(String path, String data, String encoding) {
- try {
- createEntry(path);
- setEntryData(path, data, encoding);
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- }
-
- @Override
- public int setEntryData(String path, String data) {
- return setEntryData(path, data, DEFAULT_ENCODING);
- }
-
- @Override
- public int setEntryData(String path, String data, String encoding) {
- int version = 0;
- try {
- Stat s = delegate.setData().forPath(path, data.getBytes(Charset.forName(encoding)));
- if (s != null) {
- version = s.getVersion();
- }
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- return version;
- }
-
- @Override
- public void deleteEntry(String path) {
- try {
- delegate.delete().forPath(path);
- } catch (Exception e) {
- log.errorInteractingWithRemoteConfigRegistry(e);
- }
- }
- }
-
- /**
- * SASL ACLProvider
- */
- private static class SASLOwnerACLProvider implements ACLProvider {
-
- private final List<ACL> saslACL;
-
- private SASLOwnerACLProvider() {
- this.saslACL = ZooDefs.Ids.CREATOR_ALL_ACL; // All permissions for any authenticated user
- }
-
- @Override
- public List<ACL> getDefaultAcl() {
- return saslACL;
- }
-
- @Override
- public List<ACL> getAclForPath(String path) {
- return getDefaultAcl();
- }
- }
-
-
- private static final class ChildEntryListenerAdapter implements PathChildrenCacheListener {
-
- private RemoteConfigurationRegistryClient client;
- private ChildEntryListener delegate;
-
- ChildEntryListenerAdapter(RemoteConfigurationRegistryClient client, ChildEntryListener delegate) {
- this.client = client;
- this.delegate = delegate;
- }
-
- @Override
- public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent)
- throws Exception {
- ChildData childData = pathChildrenCacheEvent.getData();
- if (childData != null) {
- ChildEntryListener.Type eventType = adaptType(pathChildrenCacheEvent.getType());
- if (eventType != null) {
- delegate.childEvent(client, eventType, childData.getPath());
- }
- }
- }
-
- private ChildEntryListener.Type adaptType(PathChildrenCacheEvent.Type type) {
- ChildEntryListener.Type adapted = null;
-
- switch(type) {
- case CHILD_ADDED:
- adapted = ChildEntryListener.Type.ADDED;
- break;
- case CHILD_REMOVED:
- adapted = ChildEntryListener.Type.REMOVED;
- break;
- case CHILD_UPDATED:
- adapted = ChildEntryListener.Type.UPDATED;
- break;
- }
-
- return adapted;
- }
- }
-
- private static final class EntryListenerAdapter implements NodeCacheListener {
-
- private RemoteConfigurationRegistryClient client;
- private EntryListener delegate;
- private NodeCache nodeCache;
-
- EntryListenerAdapter(RemoteConfigurationRegistryClient client, NodeCache nodeCache, EntryListener delegate) {
- this.client = client;
- this.nodeCache = nodeCache;
- this.delegate = delegate;
- }
-
- @Override
- public void nodeChanged() throws Exception {
- String path = null;
- byte[] data = null;
-
- ChildData cd = nodeCache.getCurrentData();
- if (cd != null) {
- path = cd.getPath();
- data = cd.getData();
- }
-
- if (path != null) {
- delegate.entryChanged(client, path, data);
- }
- }
- }
-
- /**
- * ACL adapter
- */
- private static final class ZooKeeperACLAdapter implements RemoteConfigurationRegistryClient.EntryACL {
- private String type;
- private String id;
- private int permissions;
-
- ZooKeeperACLAdapter(ACL acl) {
- this.permissions = acl.getPerms();
- this.type = acl.getId().getScheme();
- this.id = acl.getId().getId();
- }
-
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public String getType() {
- return type;
- }
-
- @Override
- public Object getPermissions() {
- return permissions;
- }
-
- @Override
- public boolean canRead() {
- return (permissions >= ZooDefs.Perms.READ);
- }
-
- @Override
- public boolean canWrite() {
- return (permissions >= ZooDefs.Perms.WRITE);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java b/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
deleted file mode 100644
index 0b5a693..0000000
--- a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.hadoop.gateway.service.config.remote.zk;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationMessages;
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.gateway.services.security.AliasServiceException;
-
-import javax.security.auth.login.AppConfigurationEntry;
-import javax.security.auth.login.Configuration;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Configuration decorator that adds SASL JAAS configuration to whatever JAAS config is already applied.
- */
-class RemoteConfigurationRegistryJAASConfig extends Configuration {
-
- // Underlying SASL mechanisms supported
- enum SASLMechanism {
- Unsupported,
- Kerberos,
- Digest
- }
-
- static final Map<String, String> digestLoginModules = new HashMap<>();
- static {
- digestLoginModules.put("ZOOKEEPER", "org.apache.zookeeper.server.auth.DigestLoginModule");
- }
-
- private static final RemoteConfigurationMessages log = MessagesFactory.get(RemoteConfigurationMessages.class);
-
- // Cache the current JAAS configuration
- private Configuration delegate = Configuration.getConfiguration();
-
- private AliasService aliasService;
-
- private 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) {
- this.aliasService = aliasService;
-
- // Populate context entries
- List<AppConfigurationEntry> appConfigEntries = new ArrayList<>();
- for (RemoteConfigurationRegistryConfig config : configs) {
- if (config.isSecureRegistry()) {
- contextEntries.put(config.getName(), createEntries(config));
- }
- }
-
- // If there is at least one context entry, then set this as the client configuration
- if (!contextEntries.isEmpty()) {
- // TODO: PJZ: ZooKeeper 3.6.0 will have per-client JAAS Configuration support; Upgrade ASAP!!
- // For now, set this as the static JAAS configuration
- Configuration.setConfiguration(this);
- }
- }
-
- @Override
- public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
- AppConfigurationEntry[] result = null;
-
- // First, try the delegate's context entries
- result = delegate.getAppConfigurationEntry(name);
- if (result == null || result.length < 1) {
- // Try our additional context entries
- result = contextEntries.get(name);
- }
-
- return result;
- }
-
- private AppConfigurationEntry[] createEntries(RemoteConfigurationRegistryConfig config) {
- AppConfigurationEntry[] result = null;
-
- AppConfigurationEntry entry = createEntry(config);
- if (entry != null) {
- // Only supporting a single app config entry per configuration/context
- result = new AppConfigurationEntry[1];
- result[0] = createEntry(config);
- } else {
- result = new AppConfigurationEntry[0];
- }
- return result;
- }
-
- private AppConfigurationEntry createEntry(RemoteConfigurationRegistryConfig config) {
- AppConfigurationEntry entry = null;
-
- Map<String, String> opts = new HashMap<>();
- SASLMechanism saslMechanism = getSASLMechanism(config.getAuthType());
- switch (saslMechanism) {
- case Digest:
- // Digest auth options
- opts.put("username", config.getPrincipal());
-
- char[] credential = null;
- if (aliasService != null) {
- try {
- credential = aliasService.getPasswordFromAliasForGateway(config.getCredentialAlias());
- } catch (AliasServiceException e) {
- log.unresolvedCredentialAlias(config.getCredentialAlias());
- }
- } else {
- throw new IllegalArgumentException("The AliasService is required to resolve credential aliases.");
- }
-
- if (credential != null) {
- opts.put("password", new String(credential));
- }
- break;
- case Kerberos:
- opts.put("isUseTicketCache", String.valueOf(config.isUseTicketCache()));
- opts.put("isUseKeyTab", String.valueOf(config.isUseKeyTab()));
- opts.put("keyTab", config.getKeytab());
- opts.put("principal", config.getPrincipal());
- }
-
- if (!opts.isEmpty()) {
- entry = new AppConfigurationEntry(getLoginModuleName(config.getRegistryType(), saslMechanism),
- AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
- opts);
- }
-
- return entry;
- }
-
- private static String getLoginModuleName(String registryType, SASLMechanism saslMechanism) {
- String loginModuleName = null;
-
- switch (saslMechanism) {
- case Kerberos:
- if (System.getProperty("java.vendor").contains("IBM")) {
- loginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
- } else {
- loginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
- }
- break;
- case Digest:
- loginModuleName = digestLoginModules.get(registryType.toUpperCase());
- }
- return loginModuleName;
- }
-
- private static SASLMechanism getSASLMechanism(String authType) {
- SASLMechanism result = SASLMechanism.Unsupported;
- for (SASLMechanism at : SASLMechanism.values()) {
- if (at.name().equalsIgnoreCase(authType)) {
- result = at;
- break;
- }
- }
- return result;
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientService.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientService.java b/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientService.java
deleted file mode 100644
index c4add4a..0000000
--- a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.hadoop.gateway.service.config.remote.zk;
-
-import org.apache.hadoop.gateway.services.config.client.RemoteConfigurationRegistryClientService;
-
-public interface ZooKeeperClientService extends RemoteConfigurationRegistryClientService {
-
- String TYPE = "ZooKeeper";
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientServiceProvider.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientServiceProvider.java b/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientServiceProvider.java
deleted file mode 100644
index f30d3da..0000000
--- a/gateway-service-remoteconfig/src/main/java/org/apache/hadoop/gateway/service/config/remote/zk/ZooKeeperClientServiceProvider.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.hadoop.gateway.service.config.remote.zk;
-
-import org.apache.hadoop.gateway.service.config.remote.RemoteConfigurationRegistryClientServiceProvider;
-
-
-public class ZooKeeperClientServiceProvider implements RemoteConfigurationRegistryClientServiceProvider {
-
- @Override
- public String getType() {
- return ZooKeeperClientService.TYPE;
- }
-
- @Override
- public ZooKeeperClientService newInstance() {
- return new CuratorClientService();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationMessages.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationMessages.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationMessages.java
new file mode 100644
index 0000000..057c8c5
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationMessages.java
@@ -0,0 +1,49 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote;
+
+import org.apache.knox.gateway.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+import org.apache.knox.gateway.i18n.messages.StackTrace;
+
+
+/**
+ *
+ */
+@Messages(logger="org.apache.knox.gateway.service.config.remote")
+public interface RemoteConfigurationMessages {
+
+ @Message(level = MessageLevel.WARN,
+ text = "Multiple remote configuration registries are not currently supported if any of them requires authentication.")
+ void multipleRemoteRegistryConfigurations();
+
+ @Message(level = MessageLevel.ERROR, text = "Failed to resolve the credential alias {0}")
+ void unresolvedCredentialAlias(final String alias);
+
+ @Message(level = MessageLevel.ERROR, text = "An error occurred interacting with the remote configuration registry : {0}")
+ void errorInteractingWithRemoteConfigRegistry(@StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+ @Message(level = MessageLevel.ERROR, text = "An error occurred handling the ACL for remote configuration {0} : {1}")
+ void errorHandlingRemoteConfigACL(final String path,
+ @StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+ @Message(level = MessageLevel.ERROR, text = "An error occurred setting the ACL for remote configuration {0} : {1}")
+ void errorSettingEntryACL(final String path,
+ @StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceFactory.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceFactory.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceFactory.java
new file mode 100644
index 0000000..f1719b6
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceFactory.java
@@ -0,0 +1,41 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+
+import java.util.ServiceLoader;
+
+public class RemoteConfigurationRegistryClientServiceFactory {
+
+ public static RemoteConfigurationRegistryClientService newInstance(GatewayConfig config) {
+ RemoteConfigurationRegistryClientService rcs = null;
+
+ ServiceLoader<RemoteConfigurationRegistryClientServiceProvider> providers =
+ ServiceLoader.load(RemoteConfigurationRegistryClientServiceProvider.class);
+ for (RemoteConfigurationRegistryClientServiceProvider provider : providers) {
+ rcs = provider.newInstance();
+ if (rcs != null) {
+ break;
+ }
+ }
+
+ return rcs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceProvider.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceProvider.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceProvider.java
new file mode 100644
index 0000000..8f69e47
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryClientServiceProvider.java
@@ -0,0 +1,27 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote;
+
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+
+public interface RemoteConfigurationRegistryClientServiceProvider {
+
+ String getType();
+
+ RemoteConfigurationRegistryClientService newInstance();
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryConfig.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryConfig.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryConfig.java
new file mode 100644
index 0000000..cbebad7
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/RemoteConfigurationRegistryConfig.java
@@ -0,0 +1,43 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote;
+
+public interface RemoteConfigurationRegistryConfig {
+
+ String getName();
+
+ String getRegistryType();
+
+ String getConnectionString();
+
+ String getNamespace();
+
+ boolean isSecureRegistry();
+
+ String getAuthType(); // digest, kerberos, etc...
+
+ String getPrincipal();
+
+ String getCredentialAlias();
+
+ String getKeytab();
+
+ boolean isUseTicketCache();
+
+ boolean isUseKeyTab();
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/DefaultRemoteConfigurationRegistries.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/DefaultRemoteConfigurationRegistries.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/DefaultRemoteConfigurationRegistries.java
new file mode 100644
index 0000000..0b2f248
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/DefaultRemoteConfigurationRegistries.java
@@ -0,0 +1,104 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.config;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A set of RemoteConfigurationRegistry configurations based on a set of property name-value pairs.
+ */
+class DefaultRemoteConfigurationRegistries extends RemoteConfigurationRegistries {
+
+ private static final String PROPERTY_DELIM = ";";
+ private static final String PROPERTY_VALUE_DELIM = "=";
+
+ private List<RemoteConfigurationRegistry> configuredRegistries = new ArrayList<>();
+
+ /**
+ * Derive the remote registry configurations from the specified GatewayConfig.
+ *
+ * @param gc The source GatewayConfig
+ */
+ DefaultRemoteConfigurationRegistries(GatewayConfig gc) {
+ List<String> configRegistryNames = gc.getRemoteRegistryConfigurationNames();
+ for (String configRegistryName : configRegistryNames) {
+ configuredRegistries.add(extractConfigForRegistry(gc, configRegistryName));
+ }
+ }
+
+ /**
+ * Extract the configuration for the specified registry configuration name.
+ *
+ * @param gc The GatewayConfig from which to extract the registry config.
+ * @param registryName The name of the registry config.
+ *
+ * @return The resulting RemoteConfigurationRegistry object, or null.
+ */
+ private static RemoteConfigurationRegistry extractConfigForRegistry(GatewayConfig gc, String registryName) {
+ RemoteConfigurationRegistry result = new RemoteConfigurationRegistry();
+
+ result.setName(registryName);
+
+ Map<String, String> properties = parsePropertyValue(gc.getRemoteRegistryConfiguration(registryName));
+
+ result.setRegistryType(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_TYPE));
+ result.setConnectionString(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_ADDRESS));
+ result.setNamespace(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_NAMESPACE));
+ result.setAuthType(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_AUTH_TYPE));
+ result.setPrincipal(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_PRINCIPAL));
+ result.setCredentialAlias(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS));
+ result.setKeytab(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_KEYTAB));
+ result.setUseKeytab(Boolean.valueOf(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_USE_KEYTAB)));
+ result.setUseTicketCache(Boolean.valueOf(properties.get(GatewayConfig.REMOTE_CONFIG_REGISTRY_USE_TICKET_CACHE)));
+
+ return result;
+ }
+
+ /**
+ * Parse the specified registry config properties String.
+ *
+ * @param value The property value content from GatewayConfig.
+ *
+ * @return A Map of the parsed properties and their respective values.
+ */
+ private static Map<String, String> parsePropertyValue(final String value) {
+ Map<String, String> result = new HashMap<>();
+
+ if (value != null) {
+ String[] props = value.split(PROPERTY_DELIM);
+ for (String prop : props) {
+ String[] split = prop.split(PROPERTY_VALUE_DELIM);
+ String propName = split[0];
+ String propValue = (split.length > 1) ? split[1] : null;
+ result.put(propName, propValue);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ List<RemoteConfigurationRegistry> getRegistryConfigurations() {
+ return configuredRegistries;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistries.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistries.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistries.java
new file mode 100644
index 0000000..16434aa
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistries.java
@@ -0,0 +1,33 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.config;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
+
+@XmlRootElement(name="remote-configuration-registries")
+class RemoteConfigurationRegistries {
+
+ private List<RemoteConfigurationRegistry> registryConfigurations = new ArrayList<>();
+
+ @XmlElement(name="remote-configuration-registry")
+ List<RemoteConfigurationRegistry> getRegistryConfigurations() {
+ return registryConfigurations;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesAccessor.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesAccessor.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesAccessor.java
new file mode 100644
index 0000000..c32816e
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesAccessor.java
@@ -0,0 +1,60 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.config;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RemoteConfigurationRegistriesAccessor {
+
+ // System property for specifying a reference to an XML configuration external to the gateway config
+ private static final String XML_CONFIG_REFERENCE_SYSTEM_PROPERTY_NAME =
+ "org.apache.knox.gateway.remote.registry.config.file";
+
+
+ public static List<RemoteConfigurationRegistryConfig> getRemoteRegistryConfigurations(GatewayConfig gatewayConfig) {
+ List<RemoteConfigurationRegistryConfig> result = new ArrayList<>();
+
+ boolean useReferencedFile = false;
+
+ // First check for the system property pointing to a valid XML config for the remote registries
+ String remoteConfigRegistryConfigFilename = System.getProperty(XML_CONFIG_REFERENCE_SYSTEM_PROPERTY_NAME);
+ if (remoteConfigRegistryConfigFilename != null) {
+ File remoteConfigRegistryConfigFile = new File(remoteConfigRegistryConfigFilename);
+ if (remoteConfigRegistryConfigFile.exists()) {
+ useReferencedFile = true;
+ // Parse the file, and build the registry config set
+ result.addAll(RemoteConfigurationRegistriesParser.getConfig(remoteConfigRegistryConfigFilename));
+ }
+ }
+
+ // If the system property was not set to a valid reference to another config file, then try to derive the
+ // registry configurations from the gateway config.
+ if (!useReferencedFile) {
+ RemoteConfigurationRegistries remoteConfigRegistries =
+ new DefaultRemoteConfigurationRegistries(gatewayConfig);
+ result.addAll(remoteConfigRegistries.getRegistryConfigurations());
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesParser.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesParser.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesParser.java
new file mode 100644
index 0000000..f6347f8
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistriesParser.java
@@ -0,0 +1,48 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.config;
+
+import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+class RemoteConfigurationRegistriesParser {
+
+ static List<RemoteConfigurationRegistryConfig> getConfig(String configFilename) {
+ List<RemoteConfigurationRegistryConfig> result = new ArrayList<>();
+
+ File file = new File(configFilename);
+
+ try {
+ JAXBContext jaxbContext = JAXBContext.newInstance(RemoteConfigurationRegistries.class);
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ RemoteConfigurationRegistries parsedContent = (RemoteConfigurationRegistries) jaxbUnmarshaller.unmarshal(file);
+ if (parsedContent != null) {
+ result.addAll(parsedContent.getRegistryConfigurations());
+ }
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistry.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
new file mode 100644
index 0000000..1fdbd9e
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/config/RemoteConfigurationRegistry.java
@@ -0,0 +1,139 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.config;
+
+import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
+
+import javax.xml.bind.annotation.XmlElement;
+
+class RemoteConfigurationRegistry implements RemoteConfigurationRegistryConfig {
+
+ private String name;
+ private String type;
+ private String connectionString;
+ private String namespace;
+ private String authType;
+ private String principal;
+ private String credentialAlias;
+ private String keyTab;
+ private boolean useKeyTab;
+ private boolean useTicketCache;
+
+ RemoteConfigurationRegistry() {
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setRegistryType(String type) {
+ this.type = type;
+ }
+
+ public void setConnectionString(String connectionString) {
+ this.connectionString = connectionString;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public void setAuthType(String authType) {
+ this.authType = authType;
+ }
+
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ public void setCredentialAlias(String alias) {
+ this.credentialAlias = alias;
+ }
+
+ public void setUseTicketCache(boolean useTicketCache) {
+ this.useTicketCache = useTicketCache;
+ }
+
+ public void setUseKeytab(boolean useKeytab) {
+ this.useKeyTab = useKeytab;
+ }
+
+ public void setKeytab(String keytab) {
+ this.keyTab = keytab;
+ }
+
+ @XmlElement(name="name")
+ public String getName() {
+ return name;
+ }
+
+ @XmlElement(name="type")
+ public String getRegistryType() {
+ return type;
+ }
+
+ @XmlElement(name="auth-type")
+ public String getAuthType() {
+ return authType;
+ }
+
+ @XmlElement(name="principal")
+ public String getPrincipal() {
+ return principal;
+ }
+
+ @XmlElement(name="credential-alias")
+ public String getCredentialAlias() {
+ return credentialAlias;
+ }
+
+ @Override
+ @XmlElement(name="address")
+ public String getConnectionString() {
+ return connectionString;
+ }
+
+ @Override
+ @XmlElement(name="namespace")
+ public String getNamespace() {
+ return namespace;
+ }
+
+ @Override
+ @XmlElement(name="use-ticket-cache")
+ public boolean isUseTicketCache() {
+ return useTicketCache;
+ }
+
+ @Override
+ @XmlElement(name="use-key-tab")
+ public boolean isUseKeyTab() {
+ return useKeyTab;
+ }
+
+ @Override
+ @XmlElement(name="keytab")
+ public String getKeytab() {
+ return keyTab;
+ }
+
+ @Override
+ public boolean isSecureRegistry() {
+ return (getAuthType() != null);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/CuratorClientService.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/CuratorClientService.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/CuratorClientService.java
new file mode 100644
index 0000000..b97a2c6
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/CuratorClientService.java
@@ -0,0 +1,464 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.zk;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.api.ACLProvider;
+import org.apache.curator.framework.imps.DefaultACLProvider;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.NodeCache;
+import org.apache.curator.framework.recipes.cache.NodeCacheListener;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+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.GatewayConfig;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.service.config.remote.RemoteConfigurationMessages;
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient.ChildEntryListener;
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient.EntryListener;
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
+import org.apache.knox.gateway.service.config.remote.RemoteConfigurationRegistryConfig;
+import org.apache.knox.gateway.service.config.remote.config.RemoteConfigurationRegistriesAccessor;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.client.ZooKeeperSaslClient;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+import org.apache.zookeeper.data.Stat;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * RemoteConfigurationRegistryClientService implementation that employs the Curator ZooKeeper client framework.
+ */
+class CuratorClientService implements ZooKeeperClientService {
+
+ private static final String LOGIN_CONTEXT_NAME_PROPERTY = ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY;
+
+ private static final String DEFAULT_LOGIN_CONTEXT_NAME = "Client";
+
+ private static final RemoteConfigurationMessages log =
+ MessagesFactory.get(RemoteConfigurationMessages.class);
+
+ private Map<String, RemoteConfigurationRegistryClient> clients = new HashMap<>();
+
+ private AliasService aliasService = null;
+
+
+ @Override
+ public void init(GatewayConfig config, Map<String, String> options) throws ServiceLifecycleException {
+
+ List<RemoteConfigurationRegistryConfig> registryConfigs = new ArrayList<>();
+
+ // Load the remote registry configurations
+ registryConfigs.addAll(RemoteConfigurationRegistriesAccessor.getRemoteRegistryConfigurations(config));
+
+ // Configure registry authentication
+ RemoteConfigurationRegistryJAASConfig.configure(registryConfigs, aliasService);
+
+ if (registryConfigs.size() > 1) {
+ // Warn about current limit on number of supported client configurations
+ log.multipleRemoteRegistryConfigurations();
+ }
+
+ // Create the clients
+ for (RemoteConfigurationRegistryConfig registryConfig : registryConfigs) {
+ if (TYPE.equalsIgnoreCase(registryConfig.getRegistryType())) {
+ RemoteConfigurationRegistryClient registryClient = createClient(registryConfig);
+ clients.put(registryConfig.getName(), registryClient);
+ }
+ }
+ }
+
+ @Override
+ public void setAliasService(AliasService aliasService) {
+ this.aliasService = aliasService;
+ }
+
+ @Override
+ public void start() throws ServiceLifecycleException {
+ }
+
+ @Override
+ public void stop() throws ServiceLifecycleException {
+ }
+
+ @Override
+ public RemoteConfigurationRegistryClient get(String name) {
+ return clients.get(name);
+ }
+
+
+ private RemoteConfigurationRegistryClient createClient(RemoteConfigurationRegistryConfig config) {
+ ACLProvider aclProvider;
+ if (config.isSecureRegistry()) {
+ configureSasl(config);
+ aclProvider = new SASLOwnerACLProvider();
+ } else {
+ // Clear SASL system property
+ System.clearProperty(LOGIN_CONTEXT_NAME_PROPERTY);
+ aclProvider = new DefaultACLProvider();
+ }
+
+ CuratorFramework client = CuratorFrameworkFactory.builder()
+ .connectString(config.getConnectionString())
+ .retryPolicy(new ExponentialBackoffRetry(1000, 3))
+ .aclProvider(aclProvider)
+ .build();
+ client.start();
+
+ return (new ClientAdapter(client, config));
+ }
+
+
+ private void configureSasl(RemoteConfigurationRegistryConfig config) {
+ String registryName = config.getName();
+ if (registryName == null) {
+ registryName = DEFAULT_LOGIN_CONTEXT_NAME;
+ }
+ System.setProperty(LOGIN_CONTEXT_NAME_PROPERTY, registryName);
+ }
+
+
+ private static final class ClientAdapter implements RemoteConfigurationRegistryClient {
+
+ private static final String DEFAULT_ENCODING = "UTF-8";
+
+ private CuratorFramework delegate;
+
+ private RemoteConfigurationRegistryConfig config;
+
+ private Map<String, NodeCache> entryNodeCaches = new HashMap<>();
+
+ ClientAdapter(CuratorFramework delegate, RemoteConfigurationRegistryConfig config) {
+ this.delegate = delegate;
+ this.config = config;
+ }
+
+ @Override
+ public String getAddress() {
+ return config.getConnectionString();
+ }
+
+ @Override
+ public boolean isAuthenticationConfigured() {
+ return config.isSecureRegistry();
+ }
+
+ @Override
+ public boolean entryExists(String path) {
+ Stat s = null;
+ try {
+ s = delegate.checkExists().forPath(path);
+ } catch (Exception e) {
+ // Ignore
+ }
+ return (s != null);
+ }
+
+ @Override
+ public List<RemoteConfigurationRegistryClient.EntryACL> getACL(String path) {
+ List<RemoteConfigurationRegistryClient.EntryACL> acl = new ArrayList<>();
+ try {
+ List<ACL> zkACL = delegate.getACL().forPath(path);
+ if (zkACL != null) {
+ for (ACL aclEntry : zkACL) {
+ RemoteConfigurationRegistryClient.EntryACL entryACL = new ZooKeeperACLAdapter(aclEntry);
+ acl.add(entryACL);
+ }
+ }
+ } catch (Exception e) {
+ log.errorHandlingRemoteConfigACL(path, e);
+ }
+ return acl;
+ }
+
+ @Override
+ public void setACL(String path, List<EntryACL> entryACLs) {
+ // Translate the abstract ACLs into ZooKeeper ACLs
+ List<ACL> delegateACLs = new ArrayList<>();
+ for (EntryACL entryACL : entryACLs) {
+ String scheme = entryACL.getType();
+ String id = entryACL.getId();
+ int permissions = 0;
+ if (entryACL.canWrite()) {
+ permissions = ZooDefs.Perms.ALL;
+ } else if (entryACL.canRead()){
+ permissions = ZooDefs.Perms.READ;
+ }
+ delegateACLs.add(new ACL(permissions, new Id(scheme, id)));
+ }
+
+ try {
+ // Set the ACLs for the path
+ delegate.setACL().withACL(delegateACLs).forPath(path);
+ } catch (Exception e) {
+ log.errorSettingEntryACL(path, e);
+ }
+ }
+
+ @Override
+ public List<String> listChildEntries(String path) {
+ List<String> result = null;
+ try {
+ result = delegate.getChildren().forPath(path);
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ return result;
+ }
+
+ @Override
+ public void addChildEntryListener(String path, ChildEntryListener listener) throws Exception {
+ PathChildrenCache childCache = new PathChildrenCache(delegate, path, false);
+ childCache.getListenable().addListener(new ChildEntryListenerAdapter(this, listener));
+ childCache.start();
+ }
+
+ @Override
+ public void addEntryListener(String path, EntryListener listener) throws Exception {
+ NodeCache nodeCache = new NodeCache(delegate, path);
+ nodeCache.getListenable().addListener(new EntryListenerAdapter(this, nodeCache, listener));
+ nodeCache.start();
+ entryNodeCaches.put(path, nodeCache);
+ }
+
+ @Override
+ public void removeEntryListener(String path) throws Exception {
+ NodeCache nodeCache = entryNodeCaches.remove(path);
+ if (nodeCache != null) {
+ nodeCache.close();
+ }
+ }
+
+ @Override
+ public String getEntryData(String path) {
+ return getEntryData(path, DEFAULT_ENCODING);
+ }
+
+ @Override
+ public String getEntryData(String path, String encoding) {
+ String result = null;
+ try {
+ byte[] data = delegate.getData().forPath(path);
+ if (data != null) {
+ result = new String(data, Charset.forName(encoding));
+ }
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ return result;
+ }
+
+ @Override
+ public void createEntry(String path) {
+ try {
+ if (delegate.checkExists().forPath(path) == null) {
+ delegate.create().forPath(path);
+ }
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ }
+
+ @Override
+ public void createEntry(String path, String data) {
+ createEntry(path, data, DEFAULT_ENCODING);
+ }
+
+ @Override
+ public void createEntry(String path, String data, String encoding) {
+ try {
+ createEntry(path);
+ setEntryData(path, data, encoding);
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ }
+
+ @Override
+ public int setEntryData(String path, String data) {
+ return setEntryData(path, data, DEFAULT_ENCODING);
+ }
+
+ @Override
+ public int setEntryData(String path, String data, String encoding) {
+ int version = 0;
+ try {
+ Stat s = delegate.setData().forPath(path, data.getBytes(Charset.forName(encoding)));
+ if (s != null) {
+ version = s.getVersion();
+ }
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ return version;
+ }
+
+ @Override
+ public void deleteEntry(String path) {
+ try {
+ delegate.delete().forPath(path);
+ } catch (Exception e) {
+ log.errorInteractingWithRemoteConfigRegistry(e);
+ }
+ }
+ }
+
+ /**
+ * SASL ACLProvider
+ */
+ private static class SASLOwnerACLProvider implements ACLProvider {
+
+ private final List<ACL> saslACL;
+
+ private SASLOwnerACLProvider() {
+ this.saslACL = ZooDefs.Ids.CREATOR_ALL_ACL; // All permissions for any authenticated user
+ }
+
+ @Override
+ public List<ACL> getDefaultAcl() {
+ return saslACL;
+ }
+
+ @Override
+ public List<ACL> getAclForPath(String path) {
+ return getDefaultAcl();
+ }
+ }
+
+
+ private static final class ChildEntryListenerAdapter implements PathChildrenCacheListener {
+
+ private RemoteConfigurationRegistryClient client;
+ private ChildEntryListener delegate;
+
+ ChildEntryListenerAdapter(RemoteConfigurationRegistryClient client, ChildEntryListener delegate) {
+ this.client = client;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent)
+ throws Exception {
+ ChildData childData = pathChildrenCacheEvent.getData();
+ if (childData != null) {
+ ChildEntryListener.Type eventType = adaptType(pathChildrenCacheEvent.getType());
+ if (eventType != null) {
+ delegate.childEvent(client, eventType, childData.getPath());
+ }
+ }
+ }
+
+ private ChildEntryListener.Type adaptType(PathChildrenCacheEvent.Type type) {
+ ChildEntryListener.Type adapted = null;
+
+ switch(type) {
+ case CHILD_ADDED:
+ adapted = ChildEntryListener.Type.ADDED;
+ break;
+ case CHILD_REMOVED:
+ adapted = ChildEntryListener.Type.REMOVED;
+ break;
+ case CHILD_UPDATED:
+ adapted = ChildEntryListener.Type.UPDATED;
+ break;
+ }
+
+ return adapted;
+ }
+ }
+
+ private static final class EntryListenerAdapter implements NodeCacheListener {
+
+ private RemoteConfigurationRegistryClient client;
+ private EntryListener delegate;
+ private NodeCache nodeCache;
+
+ EntryListenerAdapter(RemoteConfigurationRegistryClient client, NodeCache nodeCache, EntryListener delegate) {
+ this.client = client;
+ this.nodeCache = nodeCache;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void nodeChanged() throws Exception {
+ String path = null;
+ byte[] data = null;
+
+ ChildData cd = nodeCache.getCurrentData();
+ if (cd != null) {
+ path = cd.getPath();
+ data = cd.getData();
+ }
+
+ if (path != null) {
+ delegate.entryChanged(client, path, data);
+ }
+ }
+ }
+
+ /**
+ * ACL adapter
+ */
+ private static final class ZooKeeperACLAdapter implements RemoteConfigurationRegistryClient.EntryACL {
+ private String type;
+ private String id;
+ private int permissions;
+
+ ZooKeeperACLAdapter(ACL acl) {
+ this.permissions = acl.getPerms();
+ this.type = acl.getId().getScheme();
+ this.id = acl.getId().getId();
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public Object getPermissions() {
+ return permissions;
+ }
+
+ @Override
+ public boolean canRead() {
+ return (permissions >= ZooDefs.Perms.READ);
+ }
+
+ @Override
+ public boolean canWrite() {
+ return (permissions >= ZooDefs.Perms.WRITE);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
new file mode 100644
index 0000000..f75634b
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/RemoteConfigurationRegistryJAASConfig.java
@@ -0,0 +1,179 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.zk;
+
+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;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.AliasServiceException;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Configuration decorator that adds SASL JAAS configuration to whatever JAAS config is already applied.
+ */
+class RemoteConfigurationRegistryJAASConfig extends Configuration {
+
+ // Underlying SASL mechanisms supported
+ enum SASLMechanism {
+ Unsupported,
+ Kerberos,
+ Digest
+ }
+
+ static final Map<String, String> digestLoginModules = new HashMap<>();
+ static {
+ digestLoginModules.put("ZOOKEEPER", "org.apache.zookeeper.server.auth.DigestLoginModule");
+ }
+
+ private static final RemoteConfigurationMessages log = MessagesFactory.get(RemoteConfigurationMessages.class);
+
+ // Cache the current JAAS configuration
+ private Configuration delegate = Configuration.getConfiguration();
+
+ private AliasService aliasService;
+
+ private 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) {
+ this.aliasService = aliasService;
+
+ // Populate context entries
+ List<AppConfigurationEntry> appConfigEntries = new ArrayList<>();
+ for (RemoteConfigurationRegistryConfig config : configs) {
+ if (config.isSecureRegistry()) {
+ contextEntries.put(config.getName(), createEntries(config));
+ }
+ }
+
+ // If there is at least one context entry, then set this as the client configuration
+ if (!contextEntries.isEmpty()) {
+ // TODO: PJZ: ZooKeeper 3.6.0 will have per-client JAAS Configuration support; Upgrade ASAP!!
+ // For now, set this as the static JAAS configuration
+ Configuration.setConfiguration(this);
+ }
+ }
+
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+ AppConfigurationEntry[] result = null;
+
+ // First, try the delegate's context entries
+ result = delegate.getAppConfigurationEntry(name);
+ if (result == null || result.length < 1) {
+ // Try our additional context entries
+ result = contextEntries.get(name);
+ }
+
+ return result;
+ }
+
+ private AppConfigurationEntry[] createEntries(RemoteConfigurationRegistryConfig config) {
+ AppConfigurationEntry[] result = null;
+
+ AppConfigurationEntry entry = createEntry(config);
+ if (entry != null) {
+ // Only supporting a single app config entry per configuration/context
+ result = new AppConfigurationEntry[1];
+ result[0] = createEntry(config);
+ } else {
+ result = new AppConfigurationEntry[0];
+ }
+ return result;
+ }
+
+ private AppConfigurationEntry createEntry(RemoteConfigurationRegistryConfig config) {
+ AppConfigurationEntry entry = null;
+
+ Map<String, String> opts = new HashMap<>();
+ SASLMechanism saslMechanism = getSASLMechanism(config.getAuthType());
+ switch (saslMechanism) {
+ case Digest:
+ // Digest auth options
+ opts.put("username", config.getPrincipal());
+
+ char[] credential = null;
+ if (aliasService != null) {
+ try {
+ credential = aliasService.getPasswordFromAliasForGateway(config.getCredentialAlias());
+ } catch (AliasServiceException e) {
+ log.unresolvedCredentialAlias(config.getCredentialAlias());
+ }
+ } else {
+ throw new IllegalArgumentException("The AliasService is required to resolve credential aliases.");
+ }
+
+ if (credential != null) {
+ opts.put("password", new String(credential));
+ }
+ break;
+ case Kerberos:
+ opts.put("isUseTicketCache", String.valueOf(config.isUseTicketCache()));
+ opts.put("isUseKeyTab", String.valueOf(config.isUseKeyTab()));
+ opts.put("keyTab", config.getKeytab());
+ opts.put("principal", config.getPrincipal());
+ }
+
+ if (!opts.isEmpty()) {
+ entry = new AppConfigurationEntry(getLoginModuleName(config.getRegistryType(), saslMechanism),
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ opts);
+ }
+
+ return entry;
+ }
+
+ private static String getLoginModuleName(String registryType, SASLMechanism saslMechanism) {
+ String loginModuleName = null;
+
+ switch (saslMechanism) {
+ case Kerberos:
+ if (System.getProperty("java.vendor").contains("IBM")) {
+ loginModuleName = "com.ibm.security.auth.module.Krb5LoginModule";
+ } else {
+ loginModuleName = "com.sun.security.auth.module.Krb5LoginModule";
+ }
+ break;
+ case Digest:
+ loginModuleName = digestLoginModules.get(registryType.toUpperCase());
+ }
+ return loginModuleName;
+ }
+
+ private static SASLMechanism getSASLMechanism(String authType) {
+ SASLMechanism result = SASLMechanism.Unsupported;
+ for (SASLMechanism at : SASLMechanism.values()) {
+ if (at.name().equalsIgnoreCase(authType)) {
+ result = at;
+ break;
+ }
+ }
+ return result;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/e766b3b7/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/ZooKeeperClientService.java
----------------------------------------------------------------------
diff --git a/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/ZooKeeperClientService.java b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/ZooKeeperClientService.java
new file mode 100644
index 0000000..17c93e0
--- /dev/null
+++ b/gateway-service-remoteconfig/src/main/java/org/apache/knox/gateway/service/config/remote/zk/ZooKeeperClientService.java
@@ -0,0 +1,25 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.knox.gateway.service.config.remote.zk;
+
+import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+
+public interface ZooKeeperClientService extends RemoteConfigurationRegistryClientService {
+
+ String TYPE = "ZooKeeper";
+
+}