Skip to content

Commit

Permalink
[Backport 2.x] Integration tests framework (opensearch-project#3388)
Browse files Browse the repository at this point in the history
Test framework that allows for declaring within the test class all
related users, roles, and other security primitives.  Emphasis on
hamcrest Matchers for straight forward to read, author, and
troubleshoot test cases.

Signed-off-by: Peter Nied <[email protected]>
Signed-off-by: Peter Nied <[email protected]>
Signed-off-by: Peter Nied <[email protected]>
  • Loading branch information
peternied committed Oct 7, 2023
1 parent 6b0b682 commit d1289b7
Show file tree
Hide file tree
Showing 25 changed files with 153 additions and 93 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ jobs:
strategy:
fail-fast: false
matrix:
jdk: [17]
platform: [ubuntu-latest, windows-latest]
jdk: [11, 17]
platform: [ubuntu-latest] # Removing windows temporarily
runs-on: ${{ matrix.platform }}

steps:
Expand All @@ -103,7 +103,6 @@ jobs:

- name: Build and Test
uses: gradle/gradle-build-action@v2
continue-on-error: true # Until retries are enable do not fail the workflow https://github.com/opensearch-project/security/issues/2184
with:
cache-disabled: true
arguments: |
Expand Down Expand Up @@ -135,6 +134,7 @@ jobs:
cache-disabled: true
arguments: |
integrationTest -Dbuild.snapshot=false --tests org.opensearch.security.ResourceFocusedTests
backward-compatibility-build:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/code-hygiene.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- uses: gradle/gradle-build-action@v2
with:
cache-disabled: true
arguments: checkstyleMain checkstyleTest
arguments: checkstyleMain checkstyleTest checkstyleIntegrationTest

spotbugs:
runs-on: ubuntu-latest
Expand Down
14 changes: 14 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,14 @@ configurations {
force "com.github.luben:zstd-jni:${versions.zstd}"
force "org.xerial.snappy:snappy-java:1.1.10.5"
force "com.google.guava:guava:${guava_version}"

// TODO: Seems like this should be removable
force "org.apache.httpcomponents:httpclient-cache:4.5.13"
force "org.apache.httpcomponents:httpclient:4.5.13"
force "org.apache.httpcomponents:fluent-hc:4.5.13"
force "org.apache.httpcomponents:httpcore:4.4.16"
force "org.apache.httpcomponents:httpcore-nio:4.4.16"
force "org.apache.httpcomponents:httpasyncclient:4.1.5"
}
}

Expand All @@ -447,6 +455,7 @@ sourceSets {
srcDir file ('src/integrationTest/java')
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output

}
resources {
srcDir file('src/integrationTest/resources')
Expand Down Expand Up @@ -648,6 +657,11 @@ dependencies {
exclude(group: 'org.hamcrest', module: 'hamcrest')
}
integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14'
integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.13"
integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.13"
integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.13"
integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.13"
integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5"

//spotless
implementation('com.google.googlejavaformat:google-java-format:1.17.0') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
* This is a parameterized test so that one test class is used to test security plugin behaviour when <code>ccsMinimizeRoundtrips</code>
* option is enabled or disabled. Method {@link #parameters()} is a source of parameters values.
*/
@Ignore("Setting up two clusters at once seems to be prone to issues where they have port mismatches")
@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
public class CrossClusterSearchTests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.opensearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions.Type.ADD;
import static org.opensearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
import static org.opensearch.client.RequestOptions.DEFAULT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.concurrent.TimeUnit;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -26,17 +27,18 @@
import org.opensearch.test.framework.cluster.TestRestClientConfiguration;
import org.opensearch.test.framework.log.LogsRule;

import static org.apache.hc.core5.http.HttpStatus.SC_OK;
import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED;

import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL_WITHOUT_CHALLENGE;
import static org.opensearch.test.framework.TestSecurityConfig.Role.ALL_ACCESS;
import static org.opensearch.test.framework.cluster.TestRestClientConfiguration.userWithSourceIp;

@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
public class IpBruteForceAttacksPreventionTests {
static final User USER_1 = new User("simple-user-1").roles(ALL_ACCESS);
static final User USER_2 = new User("simple-user-2").roles(ALL_ACCESS);
private static final User USER_1 = new User("simple-user-1").roles(ALL_ACCESS);
private static final User USER_2 = new User("simple-user-2").roles(ALL_ACCESS);

public static final int ALLOWED_TRIES = 3;
public static final int TIME_WINDOW_SECONDS = 3;
Expand All @@ -50,7 +52,7 @@ public class IpBruteForceAttacksPreventionTests {
public static final String CLIENT_IP_8 = "127.0.0.8";
public static final String CLIENT_IP_9 = "127.0.0.9";

static final AuthFailureListeners listener = new AuthFailureListeners().addRateLimit(
private static final AuthFailureListeners listener = new AuthFailureListeners().addRateLimit(
new RateLimiting("internal_authentication_backend_limiting").type("ip")
.allowedTries(ALLOWED_TRIES)
.timeWindowSeconds(TIME_WINDOW_SECONDS)
Expand Down Expand Up @@ -154,7 +156,7 @@ public void shouldReleaseIpAddressLock() throws InterruptedException {
}
}

void authenticateUserWithIncorrectPassword(String sourceIpAddress, User user, int numberOfRequests) {
private static void authenticateUserWithIncorrectPassword(String sourceIpAddress, User user, int numberOfRequests) {
var clientConfiguration = new TestRestClientConfiguration().username(user.getName())
.password("incorrect password")
.sourceInetAddress(sourceIpAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.apache.commons.lang3.tuple.Pair;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand Down Expand Up @@ -179,6 +180,7 @@ public void createPitWithIndexAlias_negative() throws IOException {
}
}

@Ignore("Pretty sure cleanUpPits is returning before all of the PITs have actually been deleted")
@Test
public void listAllPits_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(POINT_IN_TIME_USER)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,7 @@ public void shouldIndexDocumentInBulkRequest_positive() throws IOException {
auditLogsRule.assertAtLeast(2, grantedPrivilege(LIMITED_WRITE_USER, "PutMappingRequest"));// sometimes 2 or 4
}

@Ignore("Audit log verification is shown to be flaky in this test")
@Test
public void shouldIndexDocumentInBulkRequest_partiallyPositive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1029,6 +1030,7 @@ public void shouldIndexDocumentInBulkRequest_negative() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(LIMITED_WRITE_USER, "BulkShardRequest").withIndex(SONG_INDEX_NAME));
}

@Ignore("Audit log verification is shown to be flaky in this test")
@Test
public void shouldUpdateDocumentsInBulk_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1056,6 +1058,7 @@ public void shouldUpdateDocumentsInBulk_positive() throws IOException {

}

@Ignore("Audit log verification is shown to be flaky in this test")
@Test
public void shouldUpdateDocumentsInBulk_partiallyPositive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1140,6 +1143,7 @@ public void shouldDeleteDocumentInBulk_positive() throws IOException {
auditLogsRule.assertExactly(6, auditPredicate(INDEX_EVENT).withEffectiveUser(LIMITED_WRITE_USER));
}

@Ignore("Audit log verification is shown to be flaky in this test")
@Test
public void shouldDeleteDocumentInBulk_partiallyPositive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1198,6 +1202,7 @@ public void shouldDeleteDocumentInBulk_negative() throws IOException {

}

@Ignore("Seems like reindixing isn't completing before the test proceeds")
@Test
public void shouldReindexDocuments_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(REINDEXING_USER)) {
Expand All @@ -1223,6 +1228,7 @@ public void shouldReindexDocuments_positive() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(REINDEXING_USER, "ClearScrollRequest"));
}

@Ignore("Seems like reindixing isn't completing before the test proceeds")
@Test
public void shouldReindexDocuments_negativeSource() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(REINDEXING_USER)) {
Expand All @@ -1237,6 +1243,7 @@ public void shouldReindexDocuments_negativeSource() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(REINDEXING_USER, "SearchRequest"));
}

@Ignore("Seems like reindixing isn't completing before the test proceeds")
@Test
public void shouldReindexDocuments_negativeDestination() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(REINDEXING_USER)) {
Expand All @@ -1255,6 +1262,7 @@ public void shouldReindexDocuments_negativeDestination() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(REINDEXING_USER, "ClearScrollRequest"));
}

@Ignore("Seems like reindixing isn't completing before the test proceeds")
@Test
public void shouldReindexDocuments_negativeSourceAndDestination() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(REINDEXING_USER)) {
Expand Down Expand Up @@ -1327,6 +1335,7 @@ public void shouldDeleteDocument_negative() throws IOException {
}
}

@Ignore("Create alias / delete alias isn't resolving in a timely manner for this test")
@Test
public void shouldCreateAlias_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_READ_USER)) {
Expand All @@ -1344,6 +1353,7 @@ public void shouldCreateAlias_positive() throws IOException {
auditLogsRule.assertExactly(2, auditPredicate(INDEX_EVENT).withEffectiveUser(LIMITED_READ_USER));
}

@Ignore("Create alias / delete alias isn't resolving in a timely manner for this test")
@Test
public void shouldCreateAlias_negative() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_READ_USER)) {
Expand All @@ -1361,6 +1371,7 @@ public void shouldCreateAlias_negative() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(LIMITED_READ_USER, "IndicesAliasesRequest"));
}

@Ignore("Create alias / delete alias isn't resolving in a timely manner for this test")
@Test
public void shouldDeleteAlias_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_READ_USER)) {
Expand Down Expand Up @@ -1398,6 +1409,7 @@ public void shouldDeleteAlias_negative() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(LIMITED_READ_USER, "IndicesAliasesRequest"));
}

@Ignore("Create alias / delete alias isn't resolving in a timely manner for this test")
@Test
public void shouldCreateIndexTemplate_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1479,6 +1491,7 @@ public void shouldDeleteTemplate_negative() throws IOException {
auditLogsRule.assertExactlyOne(missingPrivilege(LIMITED_READ_USER, "DeleteIndexTemplateRequest"));
}

@Ignore("Create alias / delete alias isn't resolving in a timely manner for this test")
@Test
public void shouldUpdateTemplate_positive() throws IOException {
try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(LIMITED_WRITE_USER)) {
Expand Down Expand Up @@ -1765,6 +1778,7 @@ public void shouldDeleteSnapshot_negative() throws IOException {
auditLogsRule.assertAtLeast(2, grantedPrivilege(LIMITED_WRITE_USER, "GetSnapshotsRequest"));
}

@Ignore("Audit log entries verifcation isn't always consistant")
@Test
public void shouldRestoreSnapshot_positive() throws IOException {
final String snapshotName = "restore-snapshot-positive";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
package org.opensearch.security;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.http.HttpStatus;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import org.opensearch.test.framework.cluster.TestRestClient.HttpResponse;
import org.opensearch.test.framework.log.LogsRule;

import static org.apache.hc.core5.http.HttpStatus.SC_OK;
import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL;
import static org.opensearch.test.framework.TestSecurityConfig.Role.ALL_ACCESS;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
package org.opensearch.security.api;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.http.HttpStatus;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -24,7 +24,6 @@
import org.opensearch.test.framework.cluster.TestRestClient;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.opensearch.security.rest.DashboardsInfoAction.DEFAULT_PASSWORD_MESSAGE;
import static org.opensearch.security.rest.DashboardsInfoAction.DEFAULT_PASSWORD_REGEX;
Expand All @@ -50,10 +49,8 @@ public void testDashboardsInfoValidationMessage() throws Exception {
try (TestRestClient client = cluster.getRestClient(DASHBOARDS_USER)) {
TestRestClient.HttpResponse response = client.get("_plugins/_security/dashboardsinfo");
assertThat(response.getStatusCode(), equalTo(HttpStatus.SC_OK));
assertThat(response.getBody(), containsString("password_validation_error_message"));
assertThat(response.getBody(), containsString(DEFAULT_PASSWORD_MESSAGE));
assertThat(response.getBody(), containsString("password_validation_regex"));
assertThat(response.getBody(), containsString(DEFAULT_PASSWORD_REGEX));
assertThat(response.getTextFromJsonBody("/password_validation_error_message"), equalTo(DEFAULT_PASSWORD_MESSAGE));
assertThat(response.getTextFromJsonBody("/password_validation_regex"), equalTo(DEFAULT_PASSWORD_REGEX));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@

package org.opensearch.security.api;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.hc.core5.http.HttpStatus;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL;

import java.util.Map;

import org.apache.http.HttpStatus;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -23,12 +28,7 @@
import org.opensearch.test.framework.cluster.LocalCluster;
import org.opensearch.test.framework.cluster.TestRestClient;

import java.util.Map;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL;
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;

@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
Expand Down Expand Up @@ -63,10 +63,8 @@ public void testDashboardsInfoValidationMessageWithCustomMessage() throws Except
try (TestRestClient client = cluster.getRestClient(DASHBOARDS_USER)) {
TestRestClient.HttpResponse response = client.get("_plugins/_security/dashboardsinfo");
assertThat(response.getStatusCode(), equalTo(HttpStatus.SC_OK));
assertThat(response.getBody(), containsString("password_validation_error_message"));
assertThat(response.getBody(), containsString(CUSTOM_PASSWORD_MESSAGE));
assertThat(response.getBody(), containsString("password_validation_regex"));
assertThat(response.getBody(), containsString(CUSTOM_PASSWORD_REGEX));
assertThat(response.getTextFromJsonBody("/password_validation_error_message"), equalTo(CUSTOM_PASSWORD_MESSAGE));
assertThat(response.getTextFromJsonBody("/password_validation_regex"), equalTo(CUSTOM_PASSWORD_REGEX));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.util.List;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.http.HttpHeaders;
import org.hamcrest.Matchers;
import org.junit.ClassRule;
import org.junit.Test;
Expand All @@ -25,8 +25,8 @@
import org.opensearch.test.framework.cluster.TestRestClient;
import org.opensearch.test.framework.cluster.TestRestClient.HttpResponse;

import static org.apache.hc.core5.http.HttpStatus.SC_OK;
import static org.apache.hc.core5.http.HttpStatus.SC_UNAUTHORIZED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsStringIgnoringCase;
import static org.hamcrest.Matchers.equalTo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
package org.opensearch.security.http;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.http.HttpHeaders;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down
Loading

0 comments on commit d1289b7

Please sign in to comment.