blob: 3b52cc009d7441c1a46f2e709b9a3da22105842e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zookeeper.server.quorum.auth;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.zookeeper.PortAssignment;
import org.apache.zookeeper.ZKTestCase;
import org.apache.zookeeper.server.quorum.QuorumPeerTestBase.MainThread;
import org.apache.zookeeper.test.ClientBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* QuorumAuthTestBase provides a base class for testing quorum peer mutual
* authentication using SASL mechanisms.
*/
public class QuorumAuthTestBase extends ZKTestCase {
protected static final Logger LOG = LoggerFactory.getLogger(QuorumAuthTestBase.class);
protected List<MainThread> mt = new ArrayList<MainThread>();
protected static File jaasConfigDir;
public static void setupJaasConfig(String jaasEntries) {
try {
jaasConfigDir = ClientBase.createTmpDir();
File saslConfFile = new File(jaasConfigDir, "jaas.conf");
FileWriter fwriter = new FileWriter(saslConfFile);
fwriter.write(jaasEntries);
fwriter.close();
System.setProperty("java.security.auth.login.config", saslConfFile.getAbsolutePath());
} catch (IOException ioe) {
LOG.error("Failed to create tmp directory to hold JAAS conf file", ioe);
// could not create tmp directory to hold JAAS conf file : test will
// fail now.
}
}
public static void cleanupJaasConfig() {
if (jaasConfigDir != null) {
FileUtils.deleteQuietly(jaasConfigDir);
}
}
protected String startQuorum(final int serverCount, Map<String, String> authConfigs,
int authServerCount) throws IOException {
return this.startQuorum(serverCount, authConfigs, authServerCount, false);
}
protected String startMultiAddressQuorum(final int serverCount, Map<String, String> authConfigs,
int authServerCount) throws IOException {
return this.startQuorum(serverCount, authConfigs, authServerCount, true);
}
protected String startQuorum(
final int serverCount,
Map<String, String> authConfigs,
int authServerCount,
boolean multiAddress) throws IOException {
StringBuilder connectStr = new StringBuilder();
final int[] clientPorts = startQuorum(serverCount, connectStr, authConfigs, authServerCount, multiAddress);
for (int i = 0; i < serverCount; i++) {
assertTrue(
"waiting for server " + i + " being up",
ClientBase.waitForServerUp("127.0.0.1:" + clientPorts[i], ClientBase.CONNECTION_TIMEOUT));
}
return connectStr.toString();
}
protected int[] startQuorum(final int serverCount, StringBuilder connectStr, Map<String, String> authConfigs,
int authServerCount, boolean multiAddress) throws IOException {
final int[] clientPorts = new int[serverCount];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < serverCount; i++) {
clientPorts[i] = PortAssignment.unique();
String server = String.format("server.%d=localhost:%d:%d", i, PortAssignment.unique(), PortAssignment.unique());
if (multiAddress) {
server = server + String.format("|localhost:%d:%d", PortAssignment.unique(), PortAssignment.unique());
}
sb.append(server + ":participant\n");
connectStr.append("127.0.0.1:" + clientPorts[i]);
if (i < serverCount - 1) {
connectStr.append(",");
}
}
String quorumCfg = sb.toString();
// servers with authentication interfaces configured
int i = 0;
for (; i < authServerCount; i++) {
startServer(authConfigs, clientPorts, quorumCfg, i);
}
// servers without any authentication configured
for (int j = 0; j < serverCount - authServerCount; j++, i++) {
MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg);
mt.add(mthread);
mthread.start();
}
return clientPorts;
}
private void startServer(
Map<String, String> authConfigs,
final int[] clientPorts,
String quorumCfg,
int i) throws IOException {
MainThread mthread = new MainThread(i, clientPorts[i], quorumCfg, authConfigs);
mt.add(mthread);
mthread.start();
}
protected void startServer(MainThread restartPeer, Map<String, String> authConfigs) throws IOException {
MainThread mthread = new MainThread(restartPeer.getMyid(), restartPeer.getClientPort(), restartPeer.getQuorumCfgSection(), authConfigs);
mt.add(mthread);
mthread.start();
}
void shutdownAll() {
for (int i = 0; i < mt.size(); i++) {
shutdown(i);
}
}
MainThread shutdown(int index) {
MainThread mainThread = mt.get(index);
try {
mainThread.shutdown();
} catch (InterruptedException e) {
// no op
} finally {
mt.remove(index);
}
mainThread.deleteBaseDir();
return mainThread;
}
}