|
@@ -0,0 +1,410 @@
|
|
|
+/*
|
|
|
+ * 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.admin;
|
|
|
+
|
|
|
+import static org.apache.zookeeper.ZooDefs.Ids.OPEN_ACL_UNSAFE;
|
|
|
+import static org.apache.zookeeper.server.admin.Commands.AUTH_INFO_SEPARATOR;
|
|
|
+import static org.apache.zookeeper.server.admin.Commands.ROOT_PATH;
|
|
|
+import static org.apache.zookeeper.server.admin.JettyAdminServerTest.HTTPS_URL_FORMAT;
|
|
|
+import static org.junit.Assert.assertThrows;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import java.io.File;
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.net.URL;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import javax.net.ssl.HttpsURLConnection;
|
|
|
+import javax.net.ssl.SSLContext;
|
|
|
+import javax.net.ssl.X509KeyManager;
|
|
|
+import javax.net.ssl.X509TrustManager;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import org.apache.zookeeper.PortAssignment;
|
|
|
+import org.apache.zookeeper.ZKTestCase;
|
|
|
+import org.apache.zookeeper.ZooDefs;
|
|
|
+import org.apache.zookeeper.ZooKeeper;
|
|
|
+import org.apache.zookeeper.client.ZKClientConfig;
|
|
|
+import org.apache.zookeeper.common.ClientX509Util;
|
|
|
+import org.apache.zookeeper.common.QuorumX509Util;
|
|
|
+import org.apache.zookeeper.common.X509Exception;
|
|
|
+import org.apache.zookeeper.data.ACL;
|
|
|
+import org.apache.zookeeper.data.Id;
|
|
|
+import org.apache.zookeeper.server.NettyServerCnxnFactory;
|
|
|
+import org.apache.zookeeper.server.ServerCnxnFactory;
|
|
|
+import org.apache.zookeeper.server.ZooKeeperServer;
|
|
|
+import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
|
|
|
+import org.apache.zookeeper.server.auth.ProviderRegistry;
|
|
|
+import org.apache.zookeeper.server.auth.X509AuthenticationProvider;
|
|
|
+import org.apache.zookeeper.test.ClientBase;
|
|
|
+import org.eclipse.jetty.http.HttpHeader;
|
|
|
+import org.junit.jupiter.api.AfterAll;
|
|
|
+import org.junit.jupiter.api.AfterEach;
|
|
|
+import org.junit.jupiter.api.BeforeAll;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.junit.jupiter.api.TestInstance;
|
|
|
+import org.junit.jupiter.api.io.TempDir;
|
|
|
+import org.junit.jupiter.params.ParameterizedTest;
|
|
|
+import org.junit.jupiter.params.provider.EnumSource;
|
|
|
+
|
|
|
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
|
|
+public class CommandAuthTest extends ZKTestCase {
|
|
|
+ private static final String DIGEST_SCHEMA = "digest";
|
|
|
+ private static final String X509_SCHEMA = "x509";
|
|
|
+ private static final String IP_SCHEMA = "ip";
|
|
|
+ private static final String ROOT_USER = "root";
|
|
|
+ private static final String ROOT_PASSWORD = "root_passwd";
|
|
|
+ private static final String AUTH_TEST_COMMAND_NAME = "authtest";
|
|
|
+ private static final String X509_SUBJECT_PRINCIPAL = "CN=localhost,OU=ZooKeeper,O=Apache,L=Unknown,ST=Unknown,C=Unknown";
|
|
|
+
|
|
|
+ public enum AuthSchema {
|
|
|
+ DIGEST,
|
|
|
+ X509,
|
|
|
+ IP
|
|
|
+ }
|
|
|
+
|
|
|
+ private final int jettyAdminPort = PortAssignment.unique();
|
|
|
+ private final String hostPort = "127.0.0.1:" + PortAssignment.unique();
|
|
|
+ private final ClientX509Util clientX509Util = new ClientX509Util();
|
|
|
+ private final QuorumX509Util quorumX509Util = new QuorumX509Util();
|
|
|
+ private ZooKeeperServer zks;
|
|
|
+ private ServerCnxnFactory cnxnFactory;
|
|
|
+ private JettyAdminServer adminServer;
|
|
|
+ private ZooKeeper zk;
|
|
|
+
|
|
|
+ @TempDir
|
|
|
+ static File dataDir;
|
|
|
+
|
|
|
+ @TempDir
|
|
|
+ static File logDir;
|
|
|
+
|
|
|
+ @BeforeAll
|
|
|
+ public void setup() throws Exception {
|
|
|
+ Commands.registerCommand(new AuthTestCommand(true, ZooDefs.Perms.ALL, ROOT_PATH));
|
|
|
+
|
|
|
+ setupTLS();
|
|
|
+
|
|
|
+ // start ZookeeperServer
|
|
|
+ System.setProperty("zookeeper.4lw.commands.whitelist", "*");
|
|
|
+ zks = new ZooKeeperServer(dataDir, logDir, 3000);
|
|
|
+ final int port = Integer.parseInt(hostPort.split(":")[1]);
|
|
|
+ cnxnFactory = ServerCnxnFactory.createFactory(port, -1);
|
|
|
+ cnxnFactory.startup(zks);
|
|
|
+ assertTrue(ClientBase.waitForServerUp(hostPort, 120000));
|
|
|
+
|
|
|
+ // start AdminServer
|
|
|
+ System.setProperty("zookeeper.admin.enableServer", "true");
|
|
|
+ System.setProperty("zookeeper.admin.serverPort", String.valueOf(jettyAdminPort));
|
|
|
+ adminServer = new JettyAdminServer();
|
|
|
+ adminServer.setZooKeeperServer(zks);
|
|
|
+ adminServer.start();
|
|
|
+ }
|
|
|
+
|
|
|
+ @AfterAll
|
|
|
+ public void tearDown() throws Exception {
|
|
|
+ clearTLS();
|
|
|
+
|
|
|
+ System.clearProperty("zookeeper.4lw.commands.whitelist");
|
|
|
+ System.clearProperty("zookeeper.admin.enableServer");
|
|
|
+ System.clearProperty("zookeeper.admin.serverPort");
|
|
|
+
|
|
|
+ if (adminServer != null) {
|
|
|
+ adminServer.shutdown();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cnxnFactory != null) {
|
|
|
+ cnxnFactory.shutdown();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (zks != null) {
|
|
|
+ zks.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ public void setupEach() throws Exception {
|
|
|
+ zk = ClientBase.createZKClient(hostPort);
|
|
|
+ }
|
|
|
+
|
|
|
+ @AfterEach
|
|
|
+ public void tearDownEach() throws Exception {
|
|
|
+ if (zk != null) {
|
|
|
+ zk.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ParameterizedTest
|
|
|
+ @EnumSource(AuthSchema.class)
|
|
|
+ public void testAuthCheck_authorized(final AuthSchema authSchema) throws Exception {
|
|
|
+ setupRootACL(authSchema);
|
|
|
+ try {
|
|
|
+ final HttpURLConnection authTestConn = sendAuthTestCommandRequest(authSchema, true);
|
|
|
+ assertEquals(HttpURLConnection.HTTP_OK, authTestConn.getResponseCode());
|
|
|
+ } finally {
|
|
|
+ addAuthInfo(zk, authSchema);
|
|
|
+ resetRootACL(zk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ParameterizedTest
|
|
|
+ @EnumSource(value = AuthSchema.class, names = {"DIGEST"})
|
|
|
+ public void testAuthCheck_notAuthorized(final AuthSchema authSchema) throws Exception {
|
|
|
+ setupRootACL(authSchema);
|
|
|
+ try {
|
|
|
+ final HttpURLConnection authTestConn = sendAuthTestCommandRequest(authSchema, false);
|
|
|
+ assertEquals(HttpURLConnection.HTTP_FORBIDDEN, authTestConn.getResponseCode());
|
|
|
+ } finally {
|
|
|
+ addAuthInfo(zk, authSchema);
|
|
|
+ resetRootACL(zk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ParameterizedTest
|
|
|
+ @EnumSource(AuthSchema.class)
|
|
|
+ public void testAuthCheck_noACL(final AuthSchema authSchema) throws Exception {
|
|
|
+ final HttpURLConnection authTestConn = sendAuthTestCommandRequest(authSchema, false);
|
|
|
+ assertEquals(HttpURLConnection.HTTP_OK, authTestConn.getResponseCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_invalidServerRequiredConfig() {
|
|
|
+ assertThrows("An active server is required for auth check",
|
|
|
+ IllegalArgumentException.class,
|
|
|
+ () -> new AuthTestCommand(false, ZooDefs.Perms.ALL, ROOT_PATH));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_noAuthInfo() {
|
|
|
+ testAuthCheck_invalidAuthInfo(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_noAuthInfoSeparator() {
|
|
|
+ final String invalidAuthInfo = String.format("%s%s%s:%s", DIGEST_SCHEMA, "", ROOT_USER, ROOT_PASSWORD);
|
|
|
+ testAuthCheck_invalidAuthInfo(invalidAuthInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_invalidAuthInfoSeparator() {
|
|
|
+ final String invalidAuthInfo = String.format("%s%s%s:%s", DIGEST_SCHEMA, ":", ROOT_USER, ROOT_PASSWORD);
|
|
|
+ testAuthCheck_invalidAuthInfo(invalidAuthInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_invalidAuthSchema() {
|
|
|
+ final String invalidAuthInfo = String.format("%s%s%s:%s", "InvalidAuthSchema", AUTH_INFO_SEPARATOR, ROOT_USER, ROOT_PASSWORD);
|
|
|
+ testAuthCheck_invalidAuthInfo(invalidAuthInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAuthCheck_authProviderNotFound() {
|
|
|
+ final String invalidAuthInfo = String.format("%s%s%s:%s", "sasl", AUTH_INFO_SEPARATOR, ROOT_USER, ROOT_PASSWORD);
|
|
|
+ testAuthCheck_invalidAuthInfo(invalidAuthInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void testAuthCheck_invalidAuthInfo(final String invalidAuthInfo) {
|
|
|
+ final CommandResponse commandResponse = Commands.runGetCommand(AUTH_TEST_COMMAND_NAME, zks, new HashMap<>(), invalidAuthInfo, null);
|
|
|
+ assertEquals(HttpServletResponse.SC_UNAUTHORIZED, commandResponse.getStatusCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class AuthTestCommand extends GetCommand {
|
|
|
+ public AuthTestCommand(final boolean serverRequired, final int perm, final String path) {
|
|
|
+ super(Arrays.asList(AUTH_TEST_COMMAND_NAME, "at"), serverRequired, new AuthRequest(perm, path));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CommandResponse runGet(ZooKeeperServer zkServer, Map<String, String> kwargs) {
|
|
|
+ return initializeResponse();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setupTLS() throws Exception {
|
|
|
+ System.setProperty("zookeeper.authProvider.x509", "org.apache.zookeeper.server.auth.X509AuthenticationProvider");
|
|
|
+ String testDataPath = System.getProperty("test.data.dir", "src/test/resources/data");
|
|
|
+
|
|
|
+ System.setProperty(clientX509Util.getSslKeystoreLocationProperty(), testDataPath + "/ssl/testKeyStore.jks");
|
|
|
+ System.setProperty(clientX509Util.getSslKeystorePasswdProperty(), "testpass");
|
|
|
+ System.setProperty(clientX509Util.getSslTruststoreLocationProperty(), testDataPath + "/ssl/testTrustStore.jks");
|
|
|
+ System.setProperty(clientX509Util.getSslTruststorePasswdProperty(), "testpass");
|
|
|
+
|
|
|
+ // client
|
|
|
+ System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, "org.apache.zookeeper.ClientCnxnSocketNetty");
|
|
|
+ System.setProperty(ZKClientConfig.SECURE_CLIENT, "true");
|
|
|
+
|
|
|
+ // server
|
|
|
+ System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory");
|
|
|
+ System.setProperty(NettyServerCnxnFactory.PORT_UNIFICATION_KEY, Boolean.TRUE.toString());
|
|
|
+
|
|
|
+ // admin server
|
|
|
+ System.setProperty(quorumX509Util.getSslKeystoreLocationProperty(), testDataPath + "/ssl/testKeyStore.jks");
|
|
|
+ System.setProperty(quorumX509Util.getSslKeystorePasswdProperty(), "testpass");
|
|
|
+ System.setProperty(quorumX509Util.getSslTruststoreLocationProperty(), testDataPath + "/ssl/testTrustStore.jks");
|
|
|
+ System.setProperty(quorumX509Util.getSslTruststorePasswdProperty(), "testpass");
|
|
|
+ System.setProperty("zookeeper.admin.forceHttps", "true");
|
|
|
+ System.setProperty("zookeeper.admin.needClientAuth", "true");
|
|
|
+
|
|
|
+ // create SSLContext
|
|
|
+ final SSLContext sslContext = SSLContext.getInstance(ClientX509Util.DEFAULT_PROTOCOL);
|
|
|
+ final X509AuthenticationProvider authProvider = (X509AuthenticationProvider) ProviderRegistry.getProvider("x509");
|
|
|
+ if (authProvider == null) {
|
|
|
+ throw new X509Exception.SSLContextException("Could not create SSLContext with x509 auth provider");
|
|
|
+ }
|
|
|
+ sslContext.init(new X509KeyManager[]{authProvider.getKeyManager()}, new X509TrustManager[]{authProvider.getTrustManager()}, null);
|
|
|
+
|
|
|
+ // set SSLSocketFactory
|
|
|
+ HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
|
|
|
+ }
|
|
|
+
|
|
|
+ public void clearTLS() {
|
|
|
+ System.clearProperty("zookeeper.authProvider.x509");
|
|
|
+
|
|
|
+ System.clearProperty(clientX509Util.getSslKeystoreLocationProperty());
|
|
|
+ System.clearProperty(clientX509Util.getSslKeystorePasswdProperty());
|
|
|
+ System.clearProperty(clientX509Util.getSslTruststoreLocationProperty());
|
|
|
+ System.clearProperty(clientX509Util.getSslTruststorePasswdProperty());
|
|
|
+
|
|
|
+ // client side
|
|
|
+ System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
|
|
|
+ System.clearProperty(ZKClientConfig.SECURE_CLIENT);
|
|
|
+
|
|
|
+ // server side
|
|
|
+ System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
|
|
|
+ System.clearProperty(NettyServerCnxnFactory.PORT_UNIFICATION_KEY);
|
|
|
+
|
|
|
+ // admin server
|
|
|
+ System.clearProperty(quorumX509Util.getSslKeystoreLocationProperty());
|
|
|
+ System.clearProperty(quorumX509Util.getSslKeystorePasswdProperty());
|
|
|
+ System.clearProperty(quorumX509Util.getSslTruststoreLocationProperty());
|
|
|
+ System.clearProperty(quorumX509Util.getSslTruststorePasswdProperty());
|
|
|
+ System.clearProperty("zookeeper.admin.forceHttps");
|
|
|
+ System.clearProperty("zookeeper.admin.needClientAuth");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setupRootACL(final AuthSchema authSchema) throws Exception {
|
|
|
+ switch (authSchema) {
|
|
|
+ case DIGEST:
|
|
|
+ setupRootACLForDigest(zk);
|
|
|
+ break;
|
|
|
+ case X509:
|
|
|
+ setupRootACLForX509(zk);
|
|
|
+ break;
|
|
|
+ case IP:
|
|
|
+ setupRootACLForIP(zk);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new IllegalArgumentException("Unknown auth schema");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private HttpURLConnection sendAuthTestCommandRequest(final AuthSchema authSchema, final boolean validAuthInfo) throws Exception {
|
|
|
+ final URL authTestURL = new URL(String.format(HTTPS_URL_FORMAT + "/" + AUTH_TEST_COMMAND_NAME, jettyAdminPort));
|
|
|
+ final HttpURLConnection authTestConn = (HttpURLConnection) authTestURL.openConnection();
|
|
|
+ addAuthHeader(authTestConn, authSchema, validAuthInfo);
|
|
|
+ authTestConn.setRequestMethod("GET");
|
|
|
+ return authTestConn;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addAuthInfo(final ZooKeeper zk, final AuthSchema authSchema) {
|
|
|
+ switch (authSchema) {
|
|
|
+ case DIGEST:
|
|
|
+ addAuthInfoForDigest(zk);
|
|
|
+ break;
|
|
|
+ case X509:
|
|
|
+ addAuthInfoForX509(zk);
|
|
|
+ break;
|
|
|
+ case IP:
|
|
|
+ addAuthInfoForIP(zk);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new IllegalArgumentException("Unknown auth schema");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void resetRootACL(final ZooKeeper zk) throws Exception {
|
|
|
+ zk.setACL(Commands.ROOT_PATH, OPEN_ACL_UNSAFE, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void setupRootACLForDigest(final ZooKeeper zk) throws Exception {
|
|
|
+ final String idPassword = String.format("%s:%s", ROOT_USER, ROOT_PASSWORD);
|
|
|
+ final String digest = DigestAuthenticationProvider.generateDigest(idPassword);
|
|
|
+
|
|
|
+ final ACL acl = new ACL(ZooDefs.Perms.ALL, new Id(DIGEST_SCHEMA, digest));
|
|
|
+ zk.setACL(Commands.ROOT_PATH, Collections.singletonList(acl), -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void setupRootACLForX509(final ZooKeeper zk) throws Exception {
|
|
|
+ final ACL acl = new ACL(ZooDefs.Perms.ALL, new Id(X509_SCHEMA, X509_SUBJECT_PRINCIPAL));
|
|
|
+ zk.setACL(Commands.ROOT_PATH, Collections.singletonList(acl), -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void setupRootACLForIP(final ZooKeeper zk) throws Exception {
|
|
|
+ final ACL acl = new ACL(ZooDefs.Perms.ALL, new Id(IP_SCHEMA, "127.0.0.1"));
|
|
|
+ zk.setACL(Commands.ROOT_PATH, Collections.singletonList(acl), -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void addAuthInfoForDigest(final ZooKeeper zk) {
|
|
|
+ final String idPassword = String.format("%s:%s", ROOT_USER, ROOT_PASSWORD);
|
|
|
+ zk.addAuthInfo(DIGEST_SCHEMA, idPassword.getBytes(StandardCharsets.UTF_8));
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void addAuthInfoForX509(final ZooKeeper zk) {
|
|
|
+ zk.addAuthInfo(X509_SCHEMA, X509_SUBJECT_PRINCIPAL.getBytes(StandardCharsets.UTF_8));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addAuthInfoForIP(final ZooKeeper zk) {
|
|
|
+ zk.addAuthInfo(IP_SCHEMA, "127.0.0.1".getBytes(StandardCharsets.UTF_8));
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void addAuthHeader(final HttpURLConnection conn, final AuthSchema authSchema, final boolean validAuthInfo) {
|
|
|
+ String authInfo;
|
|
|
+ switch (authSchema) {
|
|
|
+ case DIGEST:
|
|
|
+ authInfo = validAuthInfo ? buildAuthorizationForDigest() : buildInvalidAuthorizationForDigest();
|
|
|
+ break;
|
|
|
+ case X509:
|
|
|
+ authInfo = buildAuthorizationForX509();
|
|
|
+ break;
|
|
|
+ case IP:
|
|
|
+ authInfo = buildAuthorizationForIP();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new IllegalArgumentException("Unknown auth schema");
|
|
|
+ }
|
|
|
+ conn.setRequestProperty(HttpHeader.AUTHORIZATION.asString(), authInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String buildAuthorizationForDigest() {
|
|
|
+ return String.format("%s%s%s:%s", DIGEST_SCHEMA, Commands.AUTH_INFO_SEPARATOR, ROOT_USER, ROOT_PASSWORD);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String buildInvalidAuthorizationForDigest() {
|
|
|
+ return String.format("%s%s%s:%s", DIGEST_SCHEMA, Commands.AUTH_INFO_SEPARATOR, "InvalidUser", "InvalidPassword");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String buildAuthorizationForX509() {
|
|
|
+ return String.format("%s%s", X509_SCHEMA, Commands.AUTH_INFO_SEPARATOR);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String buildAuthorizationForIP() {
|
|
|
+ return String.format("%s%s", IP_SCHEMA, Commands.AUTH_INFO_SEPARATOR);
|
|
|
+ }
|
|
|
+}
|