Skip to content

Commit

Permalink
Add setting to delay initialization in order to write a test with cle…
Browse files Browse the repository at this point in the history
…arer setup and tearDown

Signed-off-by: Craig Perkins <[email protected]>
  • Loading branch information
cwperks committed Jan 3, 2024
1 parent b74d7f4 commit b3b6de7
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public static Path createConfigurationDirectory() {
String[] configurationFiles = {
"config.yml",
"action_groups.yml",
"config.yml",
"internal_users.yml",
"nodes_dn.yml",
"roles.yml",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,27 @@
import org.apache.commons.io.FileUtils;
import org.awaitility.Awaitility;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.opensearch.action.admin.cluster.health.ClusterHealthRequest;
import org.opensearch.client.Client;
import org.opensearch.security.securityconf.impl.CType;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.support.ConfigHelper;
import org.opensearch.test.framework.TestSecurityConfig.User;
import org.opensearch.test.framework.cluster.ClusterManager;
import org.opensearch.test.framework.cluster.ContextHeaderDecoratorClient;
import org.opensearch.test.framework.cluster.LocalCluster;
import org.opensearch.test.framework.cluster.TestRestClient;

import static org.hamcrest.Matchers.equalTo;
import static org.opensearch.security.configuration.ConfigurationRepository.DEFAULT_CONFIG_VERSION;
import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX;
import static org.opensearch.security.support.ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX;
import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED;
import static org.opensearch.security.support.ConfigConstants.SECURITY_UNSUPPORTED_DELAY_INITIALIZATION_SECONDS;
import static org.opensearch.test.framework.TestSecurityConfig.Role.ALL_ACCESS;

@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
Expand All @@ -46,51 +50,80 @@ public class SecurityConfigurationBootstrapTests {
private static final User USER_ADMIN = new User("admin").roles(ALL_ACCESS);

@ClassRule
public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS)
public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.SINGLENODE)
.loadConfigurationIntoIndex(false)
.defaultConfigurationInitDirectory(configurationFolder.toString())
.nodeSettings(
Map.of(
SECURITY_RESTAPI_ROLES_ENABLED,
List.of("user_" + USER_ADMIN.getName() + "__" + ALL_ACCESS.getName()),
SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX,
true
true,
SECURITY_UNSUPPORTED_DELAY_INITIALIZATION_SECONDS,
5
)
)
.build();

@BeforeClass
public static void runConfigUpdateRequestsInBgThread() {

Client client = new ContextHeaderDecoratorClient(
cluster.getInternalNodeClient(),
Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true")
);
Runnable r = new Runnable() {
public void run() {
long t = System.currentTimeMillis();
long end = t + 10000;
while (System.currentTimeMillis() < end) {
cluster.triggerConfigurationReloadForSingleCType(client, CType.CONFIG, true);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
}
}
};

new Thread(r).start();
}

@AfterClass
public static void cleanConfigurationDirectory() throws IOException {
FileUtils.deleteDirectory(configurationFolder.toFile());
}

@Test
public void shouldStillLoadSecurityConfigDuringBootstrapAndActiveConfigUpdateRequests() {
public void shouldStillLoadSecurityConfigDuringBootstrapAndActiveConfigUpdateRequests() throws Exception {
cluster.getInternalNodeClient()
.admin()
.cluster()
.health(new ClusterHealthRequest(OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX).waitForGreenStatus())
.actionGet();
Client internalNodeClient = new ContextHeaderDecoratorClient(
cluster.getInternalNodeClient(),
Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true")
);
String cd = System.getProperty("security.default_init.dir") + "/";
ConfigHelper.uploadFile(
internalNodeClient,
cd + "action_groups.yml",
OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX,
CType.ACTIONGROUPS,
DEFAULT_CONFIG_VERSION
);
ConfigHelper.uploadFile(
internalNodeClient,
cd + "config.yml",
OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX,
CType.CONFIG,
DEFAULT_CONFIG_VERSION
);
ConfigHelper.uploadFile(
internalNodeClient,
cd + "roles.yml",
OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX,
CType.ROLES,
DEFAULT_CONFIG_VERSION
);
ConfigHelper.uploadFile(
internalNodeClient,
cd + "tenants.yml",
OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX,
CType.TENANTS,
DEFAULT_CONFIG_VERSION
);
long t = System.currentTimeMillis();
long end = t + 10000;
while (System.currentTimeMillis() < end) {
cluster.triggerConfigurationReloadForCTypes(
internalNodeClient,
List.of(CType.ACTIONGROUPS, CType.CONFIG, CType.ROLES, CType.TENANTS),
true
);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
Awaitility.await().alias("Load default configuration").until(() -> client.getAuthInfo().getStatusCode(), equalTo(200));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,10 @@ private static void triggerConfigurationReload(Client client) {
}
}

public void triggerConfigurationReloadForSingleCType(Client client, CType cType, boolean ignoreFailures) {
public void triggerConfigurationReloadForCTypes(Client client, List<CType> cTypes, boolean ignoreFailures) {
ConfigUpdateResponse configUpdateResponse = client.execute(
ConfigUpdateAction.INSTANCE,
new ConfigUpdateRequest(new String[] { cType.toLCString() })
new ConfigUpdateRequest(cTypes.stream().map(CType::toLCString).toArray(String[]::new))
).actionGet();
if (!ignoreFailures && configUpdateResponse.hasFailures()) {
throw new RuntimeException("ConfigUpdateResponse produced failures: " + configUpdateResponse.failures());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,14 @@ public List<Setting<?>> getSettings() {
Property.Filtered
)
);
settings.add(
Setting.intSetting(
ConfigConstants.SECURITY_UNSUPPORTED_DELAY_INITIALIZATION_SECONDS,
0,
Property.NodeScope,
Property.Filtered
)
);

// system integration
settings.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public class ConfigurationRepository {
private final AuditLog auditLog;
private final ThreadPool threadPool;
private DynamicConfigFactory dynamicConfigFactory;
private static final int DEFAULT_CONFIG_VERSION = 2;
public static final int DEFAULT_CONFIG_VERSION = 2;
private CompletableFuture<Void> bgThreadRunner = new CompletableFuture<>();
private final Thread bgThread;
private final AtomicBoolean installDefaultConfig = new AtomicBoolean();
Expand Down Expand Up @@ -147,6 +147,15 @@ private ConfigurationRepository(
createSecurityIndexIfAbsent();
waitForSecurityIndexToBeAtLeastYellow();

int initializationDelay = settings.getAsInt(
ConfigConstants.SECURITY_UNSUPPORTED_DELAY_INITIALIZATION_SECONDS,
0
);
if (initializationDelay > 0) {
LOGGER.info("Delay initialization for {} seconds", initializationDelay);
TimeUnit.SECONDS.sleep(initializationDelay);
}

ConfigHelper.uploadFile(client, cd + "config.yml", securityIndex, CType.CONFIG, DEFAULT_CONFIG_VERSION);
ConfigHelper.uploadFile(client, cd + "roles.yml", securityIndex, CType.ROLES, DEFAULT_CONFIG_VERSION);
ConfigHelper.uploadFile(
Expand Down Expand Up @@ -396,7 +405,7 @@ public boolean reloadConfiguration(Collection<CType> configTypes) throws ConfigU
LOCK.unlock();
}
} else {
throw new ConfigUpdateAlreadyInProgressException("A config update is already imn progress");
throw new ConfigUpdateAlreadyInProgressException("A config update is already in progress");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ public enum RolesMappingResolution {
// Illegal Opcodes from here on
public static final String SECURITY_UNSUPPORTED_DISABLE_REST_AUTH_INITIALLY =
"plugins.security.unsupported.disable_rest_auth_initially";
public static final String SECURITY_UNSUPPORTED_DELAY_INITIALIZATION_SECONDS =
"plugins.security.unsupported.delay_initialization_seconds";
public static final String SECURITY_UNSUPPORTED_DISABLE_INTERTRANSPORT_AUTH_INITIALLY =
"plugins.security.unsupported.disable_intertransport_auth_initially";
public static final String SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY =
Expand Down

0 comments on commit b3b6de7

Please sign in to comment.