blob: 33d91bc91422099f899043fd0b7c063dd8455206 [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.calcite.avatica.server;
import org.apache.calcite.avatica.remote.AuthenticationType;
import org.apache.calcite.avatica.remote.AvaticaServersForTest;
import org.apache.calcite.avatica.remote.Driver.Serialization;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* Test class for HTTP Basic authentication with an (insecure) specification of the "real" user
* via an HTTP query string parameter.
*
* @see HttpQueryStringParameterRemoteUserExtractor
*/
@RunWith(Parameterized.class)
public class HttpQueryStringParameterRemoteUserExtractorTest extends HttpAuthBase {
private static final Logger LOG =
LoggerFactory.getLogger(HttpQueryStringParameterRemoteUserExtractorTest.class);
private static final AvaticaServersForTest SERVERS = new AvaticaServersForTest();
private static final Properties PROXY_SERVER_PROPERTIES = new Properties();
private final HttpServer server;
private final String missingDoAsUrl;
private final String disallowedDoAsUserUrl;
private final String allowedDoAsUserUrl;
@Parameters(name = "{0}")
public static List<Object[]> parameters() throws Exception {
SERVERS.startServers(SERVER_CONFIG);
return SERVERS.getJUnitParameters();
}
@BeforeClass
public static void loadProxyServerProperties() {
// The connecting system has one set of credentials.
PROXY_SERVER_PROPERTIES.put("avatica_user", "USER1");
PROXY_SERVER_PROPERTIES.put("avatica_password", "password1");
}
public HttpQueryStringParameterRemoteUserExtractorTest(Serialization serialization,
HttpServer server) throws Exception {
this.server = server;
int port = this.server.getPort();
// Create some JDBC urls for basic authentication with varying "doAs" configuration
missingDoAsUrl = SERVERS.getJdbcUrl(port, serialization) + ";authentication=BASIC";
// USER4 is valid for HTTP basic auth, but disallowed by the server config (below)
disallowedDoAsUserUrl = SERVERS.getJdbcUrl(port, serialization, "?doAs=USER4")
+ ";authentication=BASIC";
allowedDoAsUserUrl = SERVERS.getJdbcUrl(port, serialization, "?doAs=USER2")
+ ";authenticati0n=BASIC";
// Create and grant permissions to our users
createHsqldbUsers();
}
private static final AvaticaServerConfiguration SERVER_CONFIG = new AvaticaServerConfiguration() {
@Override public AuthenticationType getAuthenticationType() {
// HTTP Basic authentication
return AuthenticationType.BASIC;
}
@Override public String getKerberosRealm() {
return null;
}
@Override public String getKerberosPrincipal() {
return null;
}
@Override public boolean supportsImpersonation() {
// Impersonation is allowed
return true;
}
@Override public <T> T doAsRemoteUser(String remoteUserName, String remoteAddress,
Callable<T> action) throws Exception {
// We disallow the remote user "USER4", allow all others
if (remoteUserName.equals("USER4")) {
throw new RemoteUserDisallowedException("USER4 is a disallowed user!");
} else {
return action.call();
}
}
@Override public RemoteUserExtractor getRemoteUserExtractor() {
// We extract the "real" user via the "doAs" query string parameter
return new HttpQueryStringParameterRemoteUserExtractor("doAs");
}
@Override public String[] getAllowedRoles() {
return new String[] { "users" };
}
@Override public String getHashLoginServiceRealm() {
return "Avatica";
}
@Override public String getHashLoginServiceProperties() {
return HttpAuthBase.getHashLoginServicePropertiesString();
}
};
@AfterClass public static void stopServer() throws Exception {
if (null != SERVERS) {
SERVERS.stopServers();
}
}
@Test public void testUserWithDisallowedRole() throws Exception {
try {
readWriteData(missingDoAsUrl, "MISSING_DO_AS", PROXY_SERVER_PROPERTIES);
fail("Expected an exception");
} catch (RuntimeException e) {
LOG.info("Caught expected exception", e);
assertThat(e.getMessage(), containsString("Failed to execute HTTP Request, got HTTP/401"));
}
}
@Test public void testUserWithDisallowedDoAsRole() throws Exception {
try {
readWriteData(disallowedDoAsUserUrl, "DISALLOWED_USER", PROXY_SERVER_PROPERTIES);
fail("Expected an exception");
} catch (RuntimeException e) {
LOG.info("Caught expected exception", e);
assertThat(e.getMessage(), containsString("Failed to execute HTTP Request, got HTTP/403"));
}
}
@Test public void testAllowedDoAsUser() throws Exception {
// When we connect with valid credentials and provide a valid "doAs" user, things should work
readWriteData(allowedDoAsUserUrl, "ALLOWED_USER", PROXY_SERVER_PROPERTIES);
}
}
// End HttpQueryStringParameterRemoteUserExtractorTest.java