8000 Migrate CLI package to new test framework by michalvavrik · Pull Request #52007 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions tests/base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,96 @@
<artifactId>keycloak-model-jpa</artifactId>
<scope>test</scope>
</dependency>
<!--
CLI tests spawn the kcadm.sh / kcreg.sh client tools and reference
org.keycloak.client.cli.* / KcAdmMain / KcRegMain for CLI constants.
-->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-cli</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<!-- Unpack the client CLI tools (kcadm.sh / kcreg.sh) used by the cli tests -->
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-client-cli-dist</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-client-cli-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
<outputDirectory>${project.build.directory}/containers</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<!-- A separate copy of the client tools used only by the FIPS suites (see Fips*TestSuite) -->
<execution>
<id>unpack-client-cli-dist-fips</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<!-- distinct markers dir so this second unpack of the same artifact is not skipped -->
<markersDirectory>${project.build.directory}/containers-fips/dependency-markers</markersDirectory>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-client-cli-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
<outputDirectory>${project.build.directory}/containers-fips</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<!-- kcadm/kcreg tests run in FIPS mode needs following dependencies according to our FIPS documentation -->
<execution>
<id>copy-client-cli-fips-libs</id>
<phase>generate-test-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>${bouncycastle.bcfips.version}</version>
</artifactItem>
<artifactItem>
<groupId>org.bouncycastle</groupId>
<artifactId>bctls-fips</artifactId>
<version>${bouncycastle.bctls-fips.version}</version>
</artifactItem>
<artifactItem>
<groupId>org.bouncycastle</groupId>
<artifactId>bcutil-fips</artifactId>
<version>${bouncycastle.bcutilfips.version}</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/containers-fips/keycloak-client-tools/bin/client/lib</outputDirectory>
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>execute-sql</id>
Expand Down
136 changes: 136 additions & 0 deletions tests/base/src/test/java/org/keycloak/tests/cli/AbstractCliTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package org.keycloak.tests.cli;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

import jakarta.ws.rs.NotFoundException;

import org.keycloak.admin.client.Keycloak;
import org.keycloak.common.util.KeystoreUtil;
import org.keycloak.testframework.annotations.InjectAdminClient;
import org.keycloak.testframework.annotations.InjectCryptoHelper;
import org.keycloak.testframework.annotations.InjectKeycloakUrls;
import org.keycloak.testframework.crypto.CryptoHelper;
import org.keycloak.testframework.https.CertificatesConfig;
import org.keycloak.testframework.https.CertificatesConfigBuilder;
import org.keycloak.testframework.https.InjectCertificates;
import org.keycloak.testframework.https.ManagedCertificates;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.tests.cli.exec.AbstractExec;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;

/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public abstract class AbstractCliTest {

// Enables TLS on the Keycloak server (https://localhost:8443) while HTTP stays available on localhost
@InjectCertificates(config = TlsEnabledConfig.class)
ManagedCertificates managedCertificates;

@InjectKeycloakUrls
protected KeycloakUrls keycloakUrls;

@InjectAdminClient
protected Keycloak adminClient;

@InjectCryptoHelper
protected CryptoHelper cryptoHelper;

protected String serverUrl;

@BeforeEach
public void initServerUrl() {
serverUrl = getHttpBaseUrl();
}

// TODO replace hardcoded port with server API once https://github.com/keycloak/keycloak/issues/48089 is resolved
private String getHttpBaseUrl() {
try {
return new URL("http", new URL(keycloakUrls.getBase()).getHost(), 8080, "").toExternalForm();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}

protected static void assertExitCodeAndStdErrSize(AbstractExec exe, int exitCode, int stdErrLineCount) {
assertExitCodeAndStreamSizes(exe, exitCode, -1, stdErrLineCount);
}

protected static void assertExitCodeAndStreamSizes(AbstractExec exe, int exitCode, int stdOutLineCount, int stdErrLineCount) {
Assertions.assertEquals(exitCode, exe.exitCode(), "exitCode == " + exitCode);
if (stdOutLineCount != -1) {
assertLineCount("STDOUT: " + exe.stdoutString(), exe.stdoutLines(), stdOutLineCount);
}
// There is additional logging in case that BC FIPS libraries are used, so the count of logged lines don't match with the case with plain BC used
// Hence we test count of lines just with FIPS disabled
if (stdErrLineCount != -1 && isFipsDisabled()) {
assertLineCount("STDERR: " + exe.stderrString(), exe.stderrLines(), stdErrLineCount);
}
}

private static void assertLineCount(String label, List<String> lines, int count) {
if (lines.size() == count) {
return;
}
// there is some kind of race condition in 'kcreg' that results in intermittent extra empty line
if (lines.size() == count + 1) {
if ("".equals(lines.get(lines.size()-1))) {
return;
}
}
Assertions.assertEquals(lines.size(), count, label + " has " + lines.size() + " lines (expected: " + count + ")");
}

private static boolean isFipsDisabled() {
return !AbstractExec.isFips();
}

/**
* Removes a realm created on the fly through the CLI, so it does not leak into other test methods or classes.
*/
protected void removeRealmIfExists(String realm) {
try {
adminClient.realm(realm).remove();
} catch (NotFoundException e) {
// already removed
}
}

protected void assumeKeystoreTypeSupported(KeystoreUtil.KeystoreFormat keystoreType) {
List<String> supportedKeystoreTypes = Arrays.asList(cryptoHelper.getExpectedSupportedKeyStoreTypes());
Assumptions.assumeTrue(supportedKeystoreTypes.contains(keystoreType.name()),
"Keystore type '" + keystoreType + "' not supported. Supported keystore types: " + supportedKeystoreTypes);
}

protected static File resourceFile(String path) {
URL resource = AbstractCliTest.class.getClassLoader().getResource(path);
Assertions.assertNotNull(resource, "Cannot load resource from path: " + path);
return new File(resource.getFile());
}

/**
* Points the client tools at the FIPS-enabled copy built into {@code target/containers-fips} (which bundles the
* BouncyCastle FIPS provider) so the external kcadm/kcreg processes run under FIPS. Invoked from the FIPS test
* suites before any test runs; non-FIPS runs use the default client tools, which keep the non-FIPS provider.
*/
public static void useFipsClientTools() {
System.setProperty(AbstractExec.CLI_TOOLS_DIR_PROPERTY,
System.getProperty("user.dir") + "/target/containers-fips/keycloak-client-tools");
}

static class TlsEnabledConfig implements CertificatesConfig {

@Override
public CertificatesConfigBuilder configure(CertificatesConfigBuilder config) {
return config.tlsEnabled(true);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package org.keycloak.testsuite.cli;
package org.keycloak.tests.cli;

import java.io.InputStream;
import java.util.List;

import org.keycloak.common.crypto.FipsMode;
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
import org.keycloak.testsuite.cli.exec.AbstractExec;
import org.keycloak.testsuite.cli.exec.AbstractExecBuilder;
import org.keycloak.tests.cli.exec.AbstractExec;
import org.keycloak.tests.cli.exec.AbstractExecBuilder;

/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class KcAdmExec extends AbstractExec {

public static final String WORK_DIR = System.getProperty("user.dir") + "/target/containers/keycloak-client-tools";
public static final String WORK_DIR = System.getProperty(CLI_TOOLS_DIR_PROPERTY,
System.getProperty("user.dir") + "/target/containers/keycloak-client-tools");

public static final String CMD = OS_ARCH.isWindows() ? "kcadm.bat" : "kcadm.sh";

Expand Down Expand Up @@ -44,7 +43,7 @@ public static KcAdmExec execute(String args) {
public List<String> stderrLines() {
List<String> lines = super.stderrLines();
// remove the two lines with the BC provider info if FIPS
return AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.DISABLED || lines.size() < 2
return !isFips() || lines.size() < 2
? lines
: lines.subList(2, lines.size());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package org.keycloak.testsuite.cli;
package org.keycloak.tests.cli;

import java.io.InputStream;
import java.util.List;

import org.keycloak.common.crypto.FipsMode;
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
import org.keycloak.testsuite.cli.exec.AbstractExec;
import org.keycloak.testsuite.cli.exec.AbstractExecBuilder;
import org.keycloak.tests.cli.exec.AbstractExec;
import org.keycloak.tests.cli.exec.AbstractExecBuilder;

/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class KcRegExec extends AbstractExec {

public static final String WORK_DIR = System.getProperty("user.dir") + "/target/containers/keycloak-client-tools";
public static final String WORK_DIR = System.getProperty(CLI_TOOLS_DIR_PROPERTY,
System.getProperty("user.dir") + "/target/containers/keycloak-client-tools");

public static final String CMD = OS_ARCH.isWindows() ? "kcreg.bat" : "kcreg.sh";

Expand Down Expand Up @@ -44,7 +43,7 @@ public static KcRegExec execute(String args) {
public List<String> stderrLines() {
List<String> lines = super.stderrLines();
// remove the two lines with the BC provider info if FIPS
return AuthServerTestEnricher.AUTH_SERVER_FIPS_MODE == FipsMode.DISABLED || lines.size() < 2
return !isFips() || lines.size() < 2
? lines
: lines.subList(2, lines.size());
}
Expand All @@ -68,4 +67,4 @@ public KcRegExec executeAsync() {
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.keycloak.tests.cli;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;

/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class TempFileResource implements Closeable {

private File file;

public TempFileResource(String filepath) {
file = new File(filepath);
}

public TempFileResource(File file) {
this.file = file;
}

public File getFile() {
return file;
}

public String getName() {
return file.getName();
}

public String getAbsolutePath() {
return file.getAbsolutePath();
}

public boolean isFile() {
return file.isFile();
}

@Override
public void close() throws IOException {
// delete file if it exists
file.delete();
}
}
Loading
Loading
0