make authorization integration test more extensible (#11730)

This commit is contained in:
Clint Wylie 2021-09-22 08:15:30 -07:00 committed by GitHub
parent 5de26cf6d9
commit 3525c0b195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 153 additions and 122 deletions

View File

@ -66,30 +66,30 @@ import java.util.stream.Collectors;
public abstract class AbstractAuthConfigurationTest
{
private static final Logger LOG = new Logger(AbstractAuthConfigurationTest.class);
private static final String INVALID_NAME = "invalid%2Fname";
protected static final String INVALID_NAME = "invalid%2Fname";
static final String SYSTEM_SCHEMA_SEGMENTS_RESULTS_RESOURCE =
protected static final String SYSTEM_SCHEMA_SEGMENTS_RESULTS_RESOURCE =
"/results/auth_test_sys_schema_segments.json";
static final String SYSTEM_SCHEMA_SERVER_SEGMENTS_RESULTS_RESOURCE =
protected static final String SYSTEM_SCHEMA_SERVER_SEGMENTS_RESULTS_RESOURCE =
"/results/auth_test_sys_schema_server_segments.json";
static final String SYSTEM_SCHEMA_SERVERS_RESULTS_RESOURCE =
protected static final String SYSTEM_SCHEMA_SERVERS_RESULTS_RESOURCE =
"/results/auth_test_sys_schema_servers.json";
static final String SYSTEM_SCHEMA_TASKS_RESULTS_RESOURCE =
protected static final String SYSTEM_SCHEMA_TASKS_RESULTS_RESOURCE =
"/results/auth_test_sys_schema_tasks.json";
static final String SYS_SCHEMA_SEGMENTS_QUERY =
protected static final String SYS_SCHEMA_SEGMENTS_QUERY =
"SELECT * FROM sys.segments WHERE datasource IN ('auth_test')";
static final String SYS_SCHEMA_SERVERS_QUERY =
protected static final String SYS_SCHEMA_SERVERS_QUERY =
"SELECT * FROM sys.servers WHERE tier IS NOT NULL";
static final String SYS_SCHEMA_SERVER_SEGMENTS_QUERY =
protected static final String SYS_SCHEMA_SERVER_SEGMENTS_QUERY =
"SELECT * FROM sys.server_segments WHERE segment_id LIKE 'auth_test%'";
static final String SYS_SCHEMA_TASKS_QUERY =
protected static final String SYS_SCHEMA_TASKS_QUERY =
"SELECT * FROM sys.tasks WHERE datasource IN ('auth_test')";
static final TypeReference<List<Map<String, Object>>> SYS_SCHEMA_RESULTS_TYPE_REFERENCE =
protected static final TypeReference<List<Map<String, Object>>> SYS_SCHEMA_RESULTS_TYPE_REFERENCE =
new TypeReference<List<Map<String, Object>>>()
{
};
@ -98,7 +98,7 @@ public abstract class AbstractAuthConfigurationTest
* create a ResourceAction set of permissions that can only read a 'auth_test' datasource, for Authorizer
* implementations which use ResourceAction pattern matching
*/
static final List<ResourceAction> DATASOURCE_ONLY_PERMISSIONS = Collections.singletonList(
protected static final List<ResourceAction> DATASOURCE_ONLY_PERMISSIONS = Collections.singletonList(
new ResourceAction(
new Resource("auth_test", ResourceType.DATASOURCE),
Action.READ
@ -109,7 +109,7 @@ public abstract class AbstractAuthConfigurationTest
* create a ResourceAction set of permissions that can only read 'auth_test' + partial SYSTEM_TABLE, for Authorizer
* implementations which use ResourceAction pattern matching
*/
static final List<ResourceAction> DATASOURCE_SYS_PERMISSIONS = ImmutableList.of(
protected static final List<ResourceAction> DATASOURCE_SYS_PERMISSIONS = ImmutableList.of(
new ResourceAction(
new Resource("auth_test", ResourceType.DATASOURCE),
Action.READ
@ -138,7 +138,7 @@ public abstract class AbstractAuthConfigurationTest
* create a ResourceAction set of permissions that can only read 'auth_test' + STATE + SYSTEM_TABLE read access, for
* Authorizer implementations which use ResourceAction pattern matching
*/
static final List<ResourceAction> DATASOURCE_SYS_STATE_PERMISSIONS = ImmutableList.of(
protected static final List<ResourceAction> DATASOURCE_SYS_STATE_PERMISSIONS = ImmutableList.of(
new ResourceAction(
new Resource("auth_test", ResourceType.DATASOURCE),
Action.READ
@ -157,7 +157,7 @@ public abstract class AbstractAuthConfigurationTest
* create a ResourceAction set of permissions with only STATE and SYSTEM_TABLE read access, for Authorizer
* implementations which use ResourceAction pattern matching
*/
static final List<ResourceAction> STATE_ONLY_PERMISSIONS = ImmutableList.of(
protected static final List<ResourceAction> STATE_ONLY_PERMISSIONS = ImmutableList.of(
new ResourceAction(
new Resource(".*", ResourceType.STATE),
Action.READ
@ -168,44 +168,42 @@ public abstract class AbstractAuthConfigurationTest
)
);
List<Map<String, Object>> adminSegments;
List<Map<String, Object>> adminTasks;
List<Map<String, Object>> adminServers;
List<Map<String, Object>> adminServerSegments;
protected List<Map<String, Object>> adminSegments;
protected List<Map<String, Object>> adminTasks;
protected List<Map<String, Object>> adminServers;
protected List<Map<String, Object>> adminServerSegments;
@Inject
IntegrationTestingConfig config;
protected IntegrationTestingConfig config;
@Inject
ObjectMapper jsonMapper;
protected ObjectMapper jsonMapper;
@Inject
@Client
HttpClient httpClient;
protected HttpClient httpClient;
@Inject
CoordinatorResourceTestClient coordinatorClient;
protected CoordinatorResourceTestClient coordinatorClient;
HttpClient adminClient;
HttpClient datasourceOnlyUserClient;
HttpClient datasourceAndSysUserClient;
HttpClient datasourceWithStateUserClient;
HttpClient stateOnlyUserClient;
HttpClient internalSystemClient;
protected HttpClient adminClient;
protected HttpClient datasourceOnlyUserClient;
protected HttpClient datasourceAndSysUserClient;
protected HttpClient datasourceWithStateUserClient;
protected HttpClient stateOnlyUserClient;
protected HttpClient internalSystemClient;
abstract void setupDatasourceOnlyUser() throws Exception;
abstract void setupDatasourceAndSysTableUser() throws Exception;
abstract void setupDatasourceAndSysAndStateUser() throws Exception;
abstract void setupSysTableAndStateOnlyUser() throws Exception;
abstract void setupTestSpecificHttpClients() throws Exception;
abstract String getAuthenticatorName();
abstract String getAuthorizerName();
abstract String getExpectedAvaticaAuthError();
protected abstract void setupDatasourceOnlyUser() throws Exception;
protected abstract void setupDatasourceAndSysTableUser() throws Exception;
protected abstract void setupDatasourceAndSysAndStateUser() throws Exception;
protected abstract void setupSysTableAndStateOnlyUser() throws Exception;
protected abstract void setupTestSpecificHttpClients() throws Exception;
protected abstract String getAuthenticatorName();
protected abstract String getAuthorizerName();
protected abstract String getExpectedAvaticaAuthError();
protected abstract Properties getAvaticaConnectionProperties();
protected abstract Properties getAvaticaConnectionPropertiesFailure();
@Test
public void test_systemSchemaAccess_admin() throws Exception
@ -417,6 +415,7 @@ public abstract class AbstractAuthConfigurationTest
Collections.emptyList()
);
}
@Test
public void test_unsecuredPathWithoutCredentials_allowed()
{
@ -496,7 +495,7 @@ public abstract class AbstractAuthConfigurationTest
verifyMaliciousUser();
}
void setupHttpClientsAndUsers() throws Exception
protected void setupHttpClientsAndUsers() throws Exception
{
setupHttpClients();
setupDatasourceOnlyUser();
@ -505,7 +504,7 @@ public abstract class AbstractAuthConfigurationTest
setupSysTableAndStateOnlyUser();
}
void checkNodeAccess(HttpClient httpClient)
protected void checkNodeAccess(HttpClient httpClient)
{
HttpUtil.makeRequest(httpClient, HttpMethod.GET, config.getCoordinatorUrl() + "/status", null);
HttpUtil.makeRequest(httpClient, HttpMethod.GET, config.getOverlordUrl() + "/status", null);
@ -514,7 +513,7 @@ public abstract class AbstractAuthConfigurationTest
HttpUtil.makeRequest(httpClient, HttpMethod.GET, config.getRouterUrl() + "/status", null);
}
void checkLoadStatus(HttpClient httpClient) throws Exception
protected void checkLoadStatus(HttpClient httpClient) throws Exception
{
checkLoadStatusSingle(httpClient, config.getCoordinatorUrl());
checkLoadStatusSingle(httpClient, config.getOverlordUrl());
@ -523,7 +522,7 @@ public abstract class AbstractAuthConfigurationTest
checkLoadStatusSingle(httpClient, config.getRouterUrl());
}
void testOptionsRequests(HttpClient httpClient)
protected void testOptionsRequests(HttpClient httpClient)
{
HttpUtil.makeRequest(httpClient, HttpMethod.OPTIONS, config.getCoordinatorUrl() + "/status", null);
HttpUtil.makeRequest(httpClient, HttpMethod.OPTIONS, config.getOverlordUrl() + "/status", null);
@ -532,18 +531,16 @@ public abstract class AbstractAuthConfigurationTest
HttpUtil.makeRequest(httpClient, HttpMethod.OPTIONS, config.getRouterUrl() + "/status", null);
}
void checkUnsecuredCoordinatorLoadQueuePath(HttpClient client)
protected void checkUnsecuredCoordinatorLoadQueuePath(HttpClient client)
{
HttpUtil.makeRequest(client, HttpMethod.GET, config.getCoordinatorUrl() + "/druid/coordinator/v1/loadqueue", null);
}
void testAvaticaQuery(String url)
protected void testAvaticaQuery(String url)
{
LOG.info("URL: " + url);
try {
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "priest");
Properties connectionProperties = getAvaticaConnectionProperties();
Connection connection = DriverManager.getConnection(url, connectionProperties);
Statement statement = connection.createStatement();
statement.setMaxRows(450);
@ -558,13 +555,11 @@ public abstract class AbstractAuthConfigurationTest
}
}
void testAvaticaAuthFailure(String url) throws Exception
protected void testAvaticaAuthFailure(String url) throws Exception
{
LOG.info("URL: " + url);
try {
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "wrongpassword");
Properties connectionProperties = getAvaticaConnectionPropertiesFailure();
Connection connection = DriverManager.getConnection(url, connectionProperties);
Statement statement = connection.createStatement();
statement.setMaxRows(450);
@ -581,9 +576,7 @@ public abstract class AbstractAuthConfigurationTest
Assert.fail("Test failed, did not get AvaticaSqlException.");
}
private void checkLoadStatusSingle(
HttpClient httpClient,
String baseUrl) throws Exception
protected void checkLoadStatusSingle(HttpClient httpClient, String baseUrl) throws Exception
{
StatusResponseHolder holder = HttpUtil.makeRequest(
httpClient,
@ -595,7 +588,7 @@ public abstract class AbstractAuthConfigurationTest
Map<String, Boolean> loadStatus = jsonMapper.readValue(content, JacksonUtils.TYPE_REFERENCE_MAP_STRING_BOOLEAN);
String authenticatorName = getAuthenticatorName();
Assert.assertNotNull(loadStatus.get(getAuthenticatorName()));
Assert.assertNotNull(loadStatus.get(authenticatorName));
Assert.assertTrue(loadStatus.get(authenticatorName));
holder = HttpUtil.makeRequest(
@ -612,7 +605,7 @@ public abstract class AbstractAuthConfigurationTest
Assert.assertTrue(loadStatus.get(authorizerName));
}
StatusResponseHolder makeSQLQueryRequest(
protected StatusResponseHolder makeSQLQueryRequest(
HttpClient httpClient,
String query,
HttpResponseStatus expectedStatus
@ -630,7 +623,7 @@ public abstract class AbstractAuthConfigurationTest
);
}
void verifySystemSchemaQueryBase(
protected void verifySystemSchemaQueryBase(
HttpClient client,
String query,
List<Map<String, Object>> expectedResults,
@ -646,7 +639,7 @@ public abstract class AbstractAuthConfigurationTest
Assert.assertEquals(responseMap, expectedResults);
}
void verifySystemSchemaQuery(
protected void verifySystemSchemaQuery(
HttpClient client,
String query,
List<Map<String, Object>> expectedResults
@ -655,7 +648,7 @@ public abstract class AbstractAuthConfigurationTest
verifySystemSchemaQueryBase(client, query, expectedResults, false);
}
void verifySystemSchemaServerQuery(
protected void verifySystemSchemaServerQuery(
HttpClient client,
String query,
List<Map<String, Object>> expectedResults
@ -664,7 +657,7 @@ public abstract class AbstractAuthConfigurationTest
verifySystemSchemaQueryBase(client, query, expectedResults, true);
}
void verifySystemSchemaQueryFailure(
protected void verifySystemSchemaQueryFailure(
HttpClient client,
String query,
HttpResponseStatus expectedErrorStatus,
@ -676,17 +669,17 @@ public abstract class AbstractAuthConfigurationTest
Assert.assertEquals(responseHolder.getContent(), expectedErrorMessage);
}
String getBrokerAvacticaUrl()
protected String getBrokerAvacticaUrl()
{
return "jdbc:avatica:remote:url=" + config.getBrokerUrl() + DruidAvaticaJsonHandler.AVATICA_PATH;
}
String getRouterAvacticaUrl()
protected String getRouterAvacticaUrl()
{
return "jdbc:avatica:remote:url=" + config.getRouterUrl() + DruidAvaticaJsonHandler.AVATICA_PATH;
}
void verifyAdminOptionsRequest()
protected void verifyAdminOptionsRequest()
{
HttpClient adminClient = new CredentialedHttpClient(
new BasicCredentials("admin", "priest"),
@ -695,7 +688,7 @@ public abstract class AbstractAuthConfigurationTest
testOptionsRequests(adminClient);
}
void verifyAuthenticationInvalidAuthNameFails()
protected void verifyAuthenticationInvalidAuthNameFails()
{
verifyInvalidAuthNameFails(StringUtils.format(
"%s/druid-ext/basic-security/authentication/listen/%s",
@ -704,7 +697,7 @@ public abstract class AbstractAuthConfigurationTest
));
}
void verifyAuthorizationInvalidAuthNameFails()
protected void verifyAuthorizationInvalidAuthNameFails()
{
verifyInvalidAuthNameFails(StringUtils.format(
"%s/druid-ext/basic-security/authorization/listen/users/%s",
@ -713,7 +706,7 @@ public abstract class AbstractAuthConfigurationTest
));
}
void verifyGroupMappingsInvalidAuthNameFails()
protected void verifyGroupMappingsInvalidAuthNameFails()
{
verifyInvalidAuthNameFails(StringUtils.format(
"%s/druid-ext/basic-security/authorization/listen/groupMappings/%s",
@ -722,7 +715,7 @@ public abstract class AbstractAuthConfigurationTest
));
}
void verifyInvalidAuthNameFails(String endpoint)
protected void verifyInvalidAuthNameFails(String endpoint)
{
HttpClient adminClient = new CredentialedHttpClient(
new BasicCredentials("admin", "priest"),
@ -738,7 +731,7 @@ public abstract class AbstractAuthConfigurationTest
);
}
void verifyMaliciousUser()
protected void verifyMaliciousUser()
{
String maliciousUsername = "<script>alert('hello')</script>";
HttpClient maliciousClient = new CredentialedHttpClient(
@ -757,14 +750,14 @@ public abstract class AbstractAuthConfigurationTest
Assert.assertFalse(responseContent.contains(maliciousUsername));
}
void setupHttpClients() throws Exception
protected void setupHttpClients() throws Exception
{
setupCommonHttpClients();
setupTestSpecificHttpClients();
}
void setupCommonHttpClients()
protected void setupCommonHttpClients()
{
adminClient = new CredentialedHttpClient(
new BasicCredentials("admin", "priest"),
@ -797,7 +790,7 @@ public abstract class AbstractAuthConfigurationTest
);
}
void setExpectedSystemSchemaObjects() throws IOException
protected void setExpectedSystemSchemaObjects() throws IOException
{
// initial setup is done now, run the system schema response content tests
adminSegments = jsonMapper.readValue(
@ -833,7 +826,7 @@ public abstract class AbstractAuthConfigurationTest
* curr_size on historicals changes because cluster state is not isolated across different
* integration tests, zero it out for consistent test results
*/
static List<Map<String, Object>> getServersWithoutCurrentSize(List<Map<String, Object>> servers)
protected static List<Map<String, Object>> getServersWithoutCurrentSize(List<Map<String, Object>> servers)
{
return Lists.transform(
servers,
@ -845,12 +838,12 @@ public abstract class AbstractAuthConfigurationTest
);
}
static String fillSegementServersTemplate(IntegrationTestingConfig config, String template)
protected static String fillSegementServersTemplate(IntegrationTestingConfig config, String template)
{
return StringUtils.replace(template, "%%HISTORICAL%%", config.getHistoricalInternalHost());
}
static String fillServersTemplate(IntegrationTestingConfig config, String template)
protected static String fillServersTemplate(IntegrationTestingConfig config, String template)
{
String json = StringUtils.replace(template, "%%HISTORICAL%%", config.getHistoricalInternalHost());
json = StringUtils.replace(json, "%%BROKER%%", config.getBrokerInternalHost());

View File

@ -36,6 +36,7 @@ import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.List;
import java.util.Properties;
@Test(groups = TestNGGroup.SECURITY)
@Guice(moduleFactory = DruidTestModuleFactory.class)
@ -69,7 +70,7 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
}
@Override
void setupDatasourceOnlyUser() throws Exception
protected void setupDatasourceOnlyUser() throws Exception
{
createUserAndRoleWithPermissions(
adminClient,
@ -81,7 +82,7 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
}
@Override
void setupDatasourceAndSysTableUser() throws Exception
protected void setupDatasourceAndSysTableUser() throws Exception
{
createUserAndRoleWithPermissions(
adminClient,
@ -93,7 +94,7 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
}
@Override
void setupDatasourceAndSysAndStateUser() throws Exception
protected void setupDatasourceAndSysAndStateUser() throws Exception
{
createUserAndRoleWithPermissions(
adminClient,
@ -105,7 +106,7 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
}
@Override
void setupSysTableAndStateOnlyUser() throws Exception
protected void setupSysTableAndStateOnlyUser() throws Exception
{
createUserAndRoleWithPermissions(
adminClient,
@ -117,7 +118,7 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
}
@Override
void setupTestSpecificHttpClients() throws Exception
protected void setupTestSpecificHttpClients() throws Exception
{
// create a new user+role that can read /status
createUserAndRoleWithPermissions(
@ -168,6 +169,42 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
);
}
@Override
protected String getAuthenticatorName()
{
return BASIC_AUTHENTICATOR;
}
@Override
protected String getAuthorizerName()
{
return BASIC_AUTHORIZER;
}
@Override
protected String getExpectedAvaticaAuthError()
{
return EXPECTED_AVATICA_AUTH_ERROR;
}
@Override
protected Properties getAvaticaConnectionProperties()
{
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "priest");
return connectionProperties;
}
@Override
protected Properties getAvaticaConnectionPropertiesFailure()
{
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "wrongpassword");
return connectionProperties;
}
private void createUserAndRoleWithPermissions(
HttpClient adminClient,
String user,
@ -239,22 +276,4 @@ public class ITBasicAuthConfigurationTest extends AbstractAuthConfigurationTest
permissionsBytes
);
}
@Override
String getAuthenticatorName()
{
return BASIC_AUTHENTICATOR;
}
@Override
String getAuthorizerName()
{
return BASIC_AUTHORIZER;
}
@Override
String getExpectedAvaticaAuthError()
{
return EXPECTED_AVATICA_AUTH_ERROR;
}
}

View File

@ -42,6 +42,7 @@ import org.testng.annotations.Test;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@Test(groups = TestNGGroup.LDAP_SECURITY)
@Guice(moduleFactory = DruidTestModuleFactory.class)
@ -119,7 +120,7 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
@Override
void setupDatasourceOnlyUser() throws Exception
protected void setupDatasourceOnlyUser() throws Exception
{
createRoleWithPermissionsAndGroupMapping(
"datasourceOnlyGroup",
@ -128,7 +129,7 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
}
@Override
void setupDatasourceAndSysTableUser() throws Exception
protected void setupDatasourceAndSysTableUser() throws Exception
{
createRoleWithPermissionsAndGroupMapping(
"datasourceWithSysGroup",
@ -137,7 +138,7 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
}
@Override
void setupDatasourceAndSysAndStateUser() throws Exception
protected void setupDatasourceAndSysAndStateUser() throws Exception
{
createRoleWithPermissionsAndGroupMapping(
"datasourceWithStateGroup",
@ -146,7 +147,7 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
}
@Override
void setupSysTableAndStateOnlyUser() throws Exception
protected void setupSysTableAndStateOnlyUser() throws Exception
{
createRoleWithPermissionsAndGroupMapping(
"stateOnlyGroup",
@ -163,7 +164,7 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
}
@Override
void setupTestSpecificHttpClients()
protected void setupTestSpecificHttpClients()
{
druidUserClient = new CredentialedHttpClient(
new BasicCredentials("druid", "helloworld"),
@ -176,6 +177,42 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
);
}
@Override
protected String getAuthenticatorName()
{
return LDAP_AUTHENTICATOR;
}
@Override
protected String getAuthorizerName()
{
return LDAP_AUTHORIZER;
}
@Override
protected String getExpectedAvaticaAuthError()
{
return EXPECTED_AVATICA_AUTH_ERROR;
}
@Override
protected Properties getAvaticaConnectionProperties()
{
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "priest");
return connectionProperties;
}
@Override
protected Properties getAvaticaConnectionPropertiesFailure()
{
Properties connectionProperties = new Properties();
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "wrongpassword");
return connectionProperties;
}
private void createRoleWithPermissionsAndGroupMapping(
String group,
Map<String, List<ResourceAction>> roleTopermissions
@ -255,22 +292,4 @@ public class ITBasicAuthLdapConfigurationTest extends AbstractAuthConfigurationT
null
);
}
@Override
String getAuthenticatorName()
{
return LDAP_AUTHENTICATOR;
}
@Override
String getAuthorizerName()
{
return LDAP_AUTHORIZER;
}
@Override
String getExpectedAvaticaAuthError()
{
return EXPECTED_AVATICA_AUTH_ERROR;
}
}