Skip to content

Commit

Permalink
New(tests): OAuth Kafka test
Browse files Browse the repository at this point in the history
  • Loading branch information
rkubis committed Mar 12, 2024
1 parent bc7cefd commit 98e7c0d
Show file tree
Hide file tree
Showing 20 changed files with 2,634 additions and 6 deletions.
1,855 changes: 1,855 additions & 0 deletions kubefiles/keycloak/keycloak_oauth_kafka-realm.yaml

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions kubefiles/keycloak/keycloak_oauth_kafka.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: registry-sso
labels:
app: sso
spec:
additionalOptions:
- name: proxy
value: edge
db:
host: keycloak-db
passwordSecret:
key: password
name: keycloak-db-secret
usernameSecret:
key: username
name: keycloak-db-secret
vendor: postgres
hostname:
hostname: registry-sso.apps.rkubis414.apicurio.integration-qe.com
ingress:
className: openshift-default
http:
httpEnabled: true
instances: 1
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<version.jackson>2.16.2</version.jackson>
<version.sundrio>0.103.1</version.sundrio>
<version.lombok>1.18.30</version.lombok>
<version.operator>1.0.0-v2.0.0.final</version.operator>
<version.operator>1.1.0-v2.4.12.final</version.operator>
<version.hamcrest>2.2</version.hamcrest>
<version.slf4j>2.0.12</version.slf4j>
<version.strimzi.api>0.39.0</version.strimzi.api>
Expand Down Expand Up @@ -261,7 +261,7 @@
<goal>wget</goal>
</goals>
<configuration>
<url>https://raw.githubusercontent.com/Apicurio/apicurio-registry-operator/${version.operator}/packagemanifests/${version.operator}/registry.apicur.io_apicurioregistries.yaml</url>
<url>https://raw.githubusercontent.com/Apicurio/apicurio-registry-operator/v${version.operator}/bundle/${version.operator}/manifests/registry.apicur.io_apicurioregistries.yaml</url>
<outputFileName>registry.apicur.io_apicurioregistries.yaml</outputFileName>
<outputDirectory>${project.build.directory}</outputDirectory>
<skipCache>true</skipCache>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,23 @@ public static boolean waitApicurioRegistryReady(ApicurioRegistry apicurioRegistr

return registryResourceType.isReady(apicurioRegistry);
}

public static ApicurioRegistry deployDefaultApicurioRegistryOAuthKafka() throws InterruptedException {
// Get Apicurio Registry
ApicurioRegistry apicurioRegistryOAuthKafka = ApicurioRegistryResourceType.getDefaultOAuthKafka(
Constants.REGISTRY,
Environment.NAMESPACE
);

CertificateUtils.createOAuthTruststore(
Environment.NAMESPACE,
Constants.OAUTH_KAFKA_ROUTER_CERTS,
Constants.OAUTH_KAFKA_TRUSTSTORE_SECRET_NAME
);

// Create Apicurio Registry
ResourceManager.getInstance().createResource(true, apicurioRegistryOAuthKafka);

return apicurioRegistryOAuthKafka;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,30 @@ public static void createTruststore(
createSecret(namespace, truststoreSecretName, secretData);
}

public static void createOAuthTruststore(
String namespace,
String caCertSecretName,
String truststoreSecretName
) throws InterruptedException {
LOGGER.info("Preparing OAuth truststore...");

String timestamp = String.valueOf(Instant.now().getEpochSecond());
String caCertSecretValue = decodeBase64Secret(namespace, caCertSecretName, "tls.crt");
Path caPath = Environment.getTmpPath("tls-" + timestamp + ".crt");

writeToFile(caCertSecretValue, caPath);

Path truststorePath = Environment.getTmpPath("truststore-" + timestamp + ".p12");

runTruststoreCmd(truststorePath, "password", caPath);

Map<String, String> secretData = new HashMap<>() {{
put("myTrustStore", Base64Utils.encode(truststorePath));
}};

createSecret(namespace, truststoreSecretName, secretData);
}

public static void createKeystore(
String namespace,
String clientCertSecretName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ public class Constants {
public static final String SSO_USER_PASSWORD = "changeme"; // Defined in kubefiles/keycloak-realm.yaml
public static final String TESTSUITE_NAMESPACE = "testsuite-namespace";

public static final String SSO_DB_SECRET_NAME = "keycloak-db-secret";
public static final String DB_PASSWORD = "password";
public static final String DB_USERNAME = "username";
public static final String OAUTH_KAFKA_TRUSTSTORE_SECRET_NAME = "mytruststore-secret";
public static final String OAUTH_KAFKA_ROUTER_CERTS = "router-certs-default";
public static final String OAUTH_KAFKA_NAME = "kafka1";

// TODO: Move other constants here too?
// PostgreSQL port
// PostgreSQL username
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,16 @@ public static void deployPostgresqlDatabase(String name, String namespace) {
e.printStackTrace();
}
}

public static void deployPostgresqlDatabase(String name, String namespace, String databaseName) {
Deployment deployment = DeploymentResourceType.getDefaultPostgresql(name, namespace, databaseName);
Service service = ServiceResourceType.getDefaultPostgresql(name, namespace);

try {
ResourceManager.getInstance().createResource(true, deployment);
ResourceManager.getInstance().createResource(false, service);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,12 @@ public static Kafka deployDefaultKafkaTls() throws InterruptedException {
public static Kafka deployDefaultKafkaScram() throws InterruptedException {
return deployDefaultKafkaByKind(KafkaKind.SCRAM);
}

public static Kafka deployDefaultOAuthKafka() throws InterruptedException {
Kafka kafka = KafkaResourceType.getDefaultOAuth();

ResourceManager.getInstance().createResource(true, kafka);

return kafka;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.apicurio.registry.systemtests.registryinfra.resources.RouteResourceType;
import io.apicurio.registry.systemtests.registryinfra.resources.ServiceResourceType;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.openshift.api.model.Route;
import org.apache.hc.core5.http.HttpStatus;
import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger;
Expand Down Expand Up @@ -39,6 +40,10 @@ public static void deployKeycloak() throws InterruptedException, IOException {
deployKeycloak(Environment.NAMESPACE);
}

public static void deployOAuthKafkaKeycloak() throws IOException, InterruptedException {
deployOAuthKafkaKeycloak(Environment.NAMESPACE);
}

private static void deployKeycloakPostgres(String namespace) throws URISyntaxException {
URL dtb = KeycloakUtils.class.getClassLoader().getResource("postgres.yaml");

Expand Down Expand Up @@ -104,6 +109,38 @@ public static void deployKeycloak(String namespace) throws InterruptedException,
LOGGER.info("Keycloak should be deployed.");
}

public static void deployOAuthKafkaKeycloak(String namespace) throws InterruptedException, IOException {
LOGGER.info("Deploying OAuth Kafka Keycloak...");
ResourceManager manager = ResourceManager.getInstance();
// Deploy Keycloak server
Exec.executeAndCheck("oc", "apply", "-n", namespace, "-f", getKeycloakFilePath("keycloak_oauth_kafka.yaml"));

// Wait for Keycloak server to be ready
Assertions.assertTrue(ResourceUtils.waitStatefulSetReady(namespace, "registry-sso"));

// Create Keycloak HTTP Service and wait for its readiness
// manager.createSharedResource( true, ServiceResourceType.getDefaultKeycloakHttp(namespace));

// Create Keycloak Route and wait for its readiness
// manager.createSharedResource( true, RouteResourceType.getDefaultOAuthKafkaKeycloak(namespace));

// Log Keycloak URL
// LOGGER.info("Keycloak URL: {}", getDefaultKeycloakURL(namespace));

// TODO: Wait for Keycloak Realm readiness, but API model not available
// Create Keycloak Realm
Exec.executeAndCheck(
"oc",
"apply",
"-n", namespace,
"-f", getKeycloakFilePath("keycloak_oauth_kafka-realm.yaml")
);

Thread.sleep(Duration.ofMinutes(1).toMillis());

LOGGER.info("Keycloak should be deployed.");
}

public static void removeKeycloakRealm(String namespace) {
LOGGER.info("Removing keycloak realm");

Expand All @@ -115,6 +152,17 @@ public static void removeKeycloakRealm(String namespace) {
);
}

public static void removeOAuthKafkaKeycloakRealm(String namespace) {
LOGGER.info("Removing OAuth Kafka keycloak realm");

Exec.executeAndCheck(
"oc",
"delete",
"-n", namespace,
"-f", getKeycloakFilePath("keycloak_oauth_kafka-realm.yaml")
);
}

public static void removeKeycloak(String namespace) throws InterruptedException {
removeKeycloakRealm(namespace);
Thread.sleep(Duration.ofMinutes(2).toMillis());
Expand All @@ -129,6 +177,20 @@ public static void removeKeycloak(String namespace) throws InterruptedException
LOGGER.info("Keycloak should be removed.");
}

public static void removeOAuthKafkaKeycloak(String namespace) throws InterruptedException {
removeOAuthKafkaKeycloakRealm(namespace);
Thread.sleep(Duration.ofMinutes(2).toMillis());
LOGGER.info("Removing OAuth Kafka Keycloak...");
Exec.executeAndCheck(
"oc",
"delete",
"-n", namespace,
"-f", getKeycloakFilePath("keycloak_oauth_kafka.yaml")
);

LOGGER.info("OAuth Kafka Keycloak should be removed.");
}

public static String getKeycloakURL(String namespace, String name, boolean secured) {
String scheme = secured ? "https://" : "http://";

Expand All @@ -151,6 +213,27 @@ public static String getDefaultKeycloakAdminURL(String namespace) {
return getKeycloakURL(namespace, "keycloak", true);
}

public static String getDefaultOAuthKafkaTokenEndpointUri() {
Route route = Kubernetes.getRouteByPrefix(Environment.NAMESPACE, Constants.SSO_NAME + "-ingress");

return "https://" + Kubernetes.getRouteHost(Environment.NAMESPACE, route.getMetadata().getName())
+ "/realms/demo/protocol/openid-connect/token";
}

public static String getDefaultOAuthKafkaJwksEndpointUri() {
Route route = Kubernetes.getRouteByPrefix(Environment.NAMESPACE, Constants.SSO_NAME + "-ingress");

return "https://" + Kubernetes.getRouteHost(Environment.NAMESPACE, route.getMetadata().getName())
+ "/realms/demo/protocol/openid-connect/certs";
}

public static String getDefaultOAuthKafkaValidIssuerUri() {
Route route = Kubernetes.getRouteByPrefix(Environment.NAMESPACE, Constants.SSO_NAME + "-ingress");

return "https://" + Kubernetes.getRouteHost(Environment.NAMESPACE, route.getMetadata().getName())
+ "/realms/demo";
}

private static HttpRequest.BodyPublisher ofFormData(Map<Object, Object> data) {
StringBuilder stringBuilder = new StringBuilder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,18 @@ public static Route getRoute(ApicurioRegistry apicurioRegistry) {
.orElse(null);
}

public static Route getRouteByPrefix(String namespace, String prefix) {
return ((OpenShiftClient) Kubernetes.getClient())
.routes()
.inNamespace(namespace)
.list()
.getItems()
.stream()
.filter(r -> r.getMetadata().getName().startsWith(prefix))
.findFirst()
.orElse(null);
}

public static void createRoute(String namespace, Route route) {
((OpenShiftClient) getClient())
.routes()
Expand Down
Loading

0 comments on commit 98e7c0d

Please sign in to comment.