Skip to content

Improve kerberos tests in testsuite to work with Podman #257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 10, 2025
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
<maven.resources.version>3.3.0</maven.resources.version>
<spotbugs.version>4.7.3</spotbugs.version>
<sonatype.nexus.staging>1.7.0</sonatype.nexus.staging>
<kafka.version>3.7.1</kafka.version>
<kafka.version>3.9.0</kafka.version>
<jackson.version>2.15.3</jackson.version>
<jackson.databind.version>2.15.3</jackson.databind.version>
<jsonpath.version>2.9.0</jsonpath.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public void starting(Description description) {

protected void outputLogs() {
// Dump the logs to stdout
environment.getContainerByServiceName("kerberos_1").ifPresent(c -> System.out.println("\n\n'kerberos' log:\n\n" + c.getLogs() + "\n"));
environment.getContainerByServiceName("kafka_1").ifPresent(c -> System.out.println("\n\n'kafka' log:\n\n" + c.getLogs() + "\n"));
environment.getContainerByServiceName("mockoauth_1").ifPresent(c -> System.out.println("\n\n'mockoauth' log:\n\n" + c.getLogs() + "\n"));
environment.getContainerByServiceName("keycloak_1").ifPresent(c -> System.out.println("\n\n'keycloak' log:\n\n" + c.getLogs() + "\n"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ public static List<String> getContainerLogsForString(String containerName, Strin
}
}

/**
* Copy a file from a container to the host using 'docker cp'.
*
* @param containerName The name of the source container
* @param srcPath The path to the source file in the container
* @param destPath The path to the destination file on the host
*/
@SuppressFBWarnings("THROWS_METHOD_THROWS_RUNTIMEEXCEPTION")
public static void copyFileFromContainer(String containerName, String srcPath, String destPath) {
try {
Process p = Runtime.getRuntime().exec(new String[] {"docker", "cp", containerName + ":" + srcPath, destPath});
p.waitFor();
} catch (Throwable e) {
throw new RuntimeException("Failed to copy file from container", e);
}
}

/**
* Helper method to wait for a condition by periodically testing the condition until it is satisfied or until timeout.
*
Expand Down
2 changes: 1 addition & 1 deletion testsuite/docker/kerberos/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM ubuntu:22.04

RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get install -y krb5-kdc krb5-admin-server

EXPOSE 88 749
EXPOSE 1088 1749

ADD ./config.sh /config.sh

Expand Down
93 changes: 61 additions & 32 deletions testsuite/docker/kerberos/config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,88 +10,117 @@
: ${KAFKA_USER:=kafka}
: ${KAFKA_HOST:=kafka}
: ${KAFKA_CLIENT_USER:=client}
: ${KDC_ADDRESS:=$(hostname -f)}
: ${KEYTABS_SHARED_DIR:=/keytabs}

fix_nameserver() {
cat>/etc/resolv.conf<<EOF
nameserver $NAMESERVER_IP
search $SEARCH_DOMAINS
EOF
}

fix_hostname() {
sed -i "/^hosts:/ s/ *files dns/ dns files/" /etc/nsswitch.conf
}

create_config() {
: ${KDC_ADDRESS:=$(hostname -f)}

cat>/etc/krb5.conf<<EOF
[logging]
default = FILE:/var/log/kerberos/krb5libs.log
kdc = FILE:/var/log/kerberos/krb5kdc.log
admin_server = FILE:/var/log/kerberos/kadmind.log

[libdefaults]
default_realm = $REALM
default_realm = KERBEROS
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
ignore_acceptor_hostname = true

[realms]
$REALM = {
kdc = $KDC_ADDRESS
admin_server = $KDC_ADDRESS
KERBEROS = {
kdc = kerberos:1088
admin_server = kerberos
}

[domain_realm]
.$DOMAIN_REALM = $REALM
$DOMAIN_REALM = $REALM
.kerberos = KERBEROS
kerberos = KERBEROS
EOF
echo "Created config: /etc/krb5.conf"
cat /etc/krb5.conf
}


create_service_config() {
cat>/etc/krb5kdc/kdc.conf<<EOF
[logging]
default = FILE:/var/log/kerberos/krb5libs.log
kdc = FILE:/var/log/kerberos/krb5kdc.log
admin_server = FILE:/var/log/kerberos/kadmind.log

[kdcdefaults]
kdc_ports = 1750,1088

[realms]
KERBEROS = {
database_name = /var/lib/krb5kdc/principal
admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
acl_file = /etc/krb5kdc/kadm5.acl
key_stash_file = /etc/krb5kdc/stash
kdc_ports = 1750,1088
max_life = 10h 0m 0s
max_renewable_life = 7d 0h 0m 0s
#master_key_type = aes256-cts
#supported_enctypes = aes256-cts:normal aes128-cts:normal
#default_principal_flags = +preauth
}
EOF
echo "Created service config: /etc/krb5kdc/kdc.conf"
cat /etc/krb5kdc/kdc.conf
}

create_db() {
kdb5_util -P $KERB_MASTER_KEY -r $REALM create -s
echo "Created db"
}

start_kdc() {
service krb5-kdc start
service krb5-admin-server start
}

restart_kdc() {
service krb5-kdc restart
service krb5-admin-server restart
}

create_admin_user() {
kadmin.local -q "addprinc -pw $KERB_ADMIN_PASS $KERB_ADMIN_USER/admin"
echo "*/admin@$REALM *" > /etc/krb5kdc/kadm5.acl
echo "Created admin user in /etc/krb5kdc/kadm5.acl"
}

create_kafka_user() {
kadmin.local -q "addprinc -randkey $KAFKA_HOST/$KAFKA_USER@$REALM"
kadmin.local -q "ktadd -k /keytabs/kafka_broker.keytab $KAFKA_HOST/$KAFKA_USER@$REALM"
kadmin.local -q "ktadd -k /etc/krb5/kafka_broker.keytab $KAFKA_HOST/$KAFKA_USER@$REALM"
kadmin.local -q "addprinc -randkey $KAFKA_HOST/$KAFKA_CLIENT_USER@$REALM"
kadmin.local -q "ktadd -k /keytabs/kafka_client.keytab $KAFKA_HOST/$KAFKA_CLIENT_USER@$REALM"
chmod 666 /keytabs/kafka_broker.keytab
chmod 666 /keytabs/kafka_client.keytab
kadmin.local -q "ktadd -k /etc/krb5/kafka_client.keytab $KAFKA_HOST/$KAFKA_CLIENT_USER@$REALM"
echo "Created keytab files for kafka user and kafka client:"
ls -la /etc/krb5
chmod 666 /etc/krb5/kafka_broker.keytab
chmod 666 /etc/krb5/kafka_client.keytab
}


copy_keytab_files() {
cp -r /etc/krb5/* $KEYTABS_SHARED_DIR
}

if [ ! -f /kerberos_initialized ]; then
mkdir -p /var/log/kerberos
mkdir /etc/krb5
echo "Created directories:"
ls -la /var/log/kerberos
ls -la /etc/krb5

create_service_config
create_config
create_db
create_admin_user
create_kafka_user
copy_keytab_files
start_kdc

touch /kerberos_initialized
else
start_kdc
fi

# Startup condition is based on the output of the log file
# See MockOAuthTests.java
tail -F /var/log/kerberos/krb5kdc.log
6 changes: 1 addition & 5 deletions testsuite/docker/kerberos/krb5.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[logging]
default = FILE:/var/log/kerberos/krb5libs.log
kdc = FILE:/var/log/kerberos/krb5kdc.log
admin_server = FILE:/var/log/kerberos/kadmind.log
[libdefaults]
default_realm = KERBEROS
dns_lookup_realm = false
Expand All @@ -13,7 +9,7 @@
ignore_acceptor_hostname = true
[realms]
KERBEROS = {
kdc = kerberos
kdc = kerberos:1088
admin_server = kerberos
}
[domain_realm]
Expand Down
2 changes: 0 additions & 2 deletions testsuite/hydra-test/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:

hydra:
Expand Down
2 changes: 0 additions & 2 deletions testsuite/keycloak-auth-tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
keycloak:
image: quay.io/keycloak/keycloak:23.0.5
Expand Down
5 changes: 2 additions & 3 deletions testsuite/keycloak-authz-kraft-tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
keycloak:
image: quay.io/keycloak/keycloak:23.0.5
Expand Down Expand Up @@ -134,8 +132,9 @@ services:
# The following value will be available as env var STRIMZI_OAUTH_METRIC_REPORTERS
- STRIMZI_OAUTH_METRIC_REPORTERS=org.apache.kafka.common.metrics.JmxReporter

# The following value will turn to 'strimzi.oauth.metric.reporters=...' in 'strimzi.properties' file
# The following value will turn into 'strimzi.oauth.metric.reporters=...' in 'strimzi.properties' file
# However, that won't work as the value may be filtered to the component that happens to initialise OAuthMetrics
# Instead, use the env var approach above
#- KAFKA_STRIMZI_OAUTH_METRIC_REPORTERS=org.apache.kafka.common.metrics.JmxReporter


Expand Down
2 changes: 0 additions & 2 deletions testsuite/keycloak-authz-tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
keycloak:
image: quay.io/keycloak/keycloak:23.0.5
Expand Down
2 changes: 0 additions & 2 deletions testsuite/keycloak-authz-zk-tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
keycloak:
image: quay.io/keycloak/keycloak:23.0.5
Expand Down
4 changes: 2 additions & 2 deletions testsuite/mock-oauth-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

<properties>
<checkstyle.dir>../..</checkstyle.dir>
<vertx.version>4.4.8</vertx.version>
<logback.version>1.3.14</logback.version>
<vertx.version>4.5.11</vertx.version>
<logback.version>1.3.15</logback.version>

<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Future<Void> ensureAuthServer(String keystorePath, String keystorePass, Mode mod

authServer = vertx.createHttpServer(new HttpServerOptions()
.setSsl(true)
.setKeyStoreOptions(keyOptions)
.setKeyCertOptions(keyOptions)
)
.requestHandler(new AuthServerRequestHandler(this))
.listen(8090)
Expand Down
18 changes: 10 additions & 8 deletions testsuite/mockoauth-tests/docker-compose-kerberos.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
mockoauth:
image: testsuite/mock-oauth-server
Expand Down Expand Up @@ -45,7 +43,7 @@ services:
- ${PWD}/../docker/kafka/scripts:/opt/kafka/strimzi
- ${PWD}/../docker/kerberos/krb5.conf:/etc/krb5.conf
- ${PWD}/../docker/kerberos/kafka_server_jaas.conf:/opt/kafka/kafka_server_jaas.conf
- ${PWD}/../docker/kerberos/keys:/opt/kafka/keytabs
- kerberos-volume:/opt/kafka/keytabs:ro
command:
- /bin/bash
- -c
Expand Down Expand Up @@ -123,6 +121,7 @@ services:
# The following value will turn into 'strimzi.oauth.metric.reporters=...' in 'strimzi.properties' file
# However, that won't work as the value may be filtered to the component that happens to initialise OAuthMetrics
#- KAFKA_STRIMZI_OAUTH_METRIC_REPORTERS=org.apache.kafka.common.metrics.JmxReporter

- KAFKA_LISTENER_NAME_KERBEROS_SASL_KERBEROS_SERVICE_NAME=kafka
- KAFKA_LISTENER_NAME_KERBEROS_SASL_ENABLED_MECHANISMS=GSSAPI
- KAFKA_OPTS=-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/kafka_server_jaas.conf
Expand All @@ -133,13 +132,13 @@ services:
- "2181:2181"
volumes:
- ${PWD}/../docker/zookeeper/scripts:/opt/kafka/strimzi
- ${PWD}/../docker/kafka/kerberos/keys:/keytabs
command:
- /bin/bash
- -c
- cd /opt/kafka/strimzi && ./start.sh
environment:
- LOG_DIR=/tmp/logs

kerberos:
build: ${PWD}/../docker/kerberos
hostname: 'kerberos'
Expand All @@ -149,8 +148,11 @@ services:
- KERB_MASTER_KEY=masterkey
- KERB_ADMIN_USER=admin
- KERB_ADMIN_PASS=admin
volumes:
- ${PWD}/../docker/kerberos/keys:/keytabs
ports:
- "749:749"
- "88:88/udp"
- "1749:1749"
- "1088:1088/udp"
volumes:
- kerberos-volume:/keytabs

volumes:
kerberos-volume:
2 changes: 0 additions & 2 deletions testsuite/mockoauth-tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
mockoauth:
image: testsuite/mock-oauth-server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ public void runTests() throws Exception {
new ClientAssertionAuthTest().doTest();

if (includeKerberosTests) {
String kerberosContainer = includeKerberosTests ? environment.getContainerByServiceName("kerberos_1").get().getContainerInfo().getName().substring(1) : null;
logStart("KerberosTests :: Test authentication with Kerberos");
new KerberosListenerTest().doTests();
new KerberosListenerTest(kerberosContainer).doTests();
}

} catch (Throwable e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
package io.strimzi.testsuite.oauth.mockoauth;

import io.strimzi.testsuite.oauth.common.TestUtil;
import org.apache.kafka.clients.admin.Admin;
import org.apache.kafka.clients.admin.CreateTopicsResult;
import org.apache.kafka.clients.admin.NewTopic;
Expand Down Expand Up @@ -31,16 +32,24 @@ public class KerberosListenerTest {
private static final long CONSUMER_TIMEOUT = 10000L;
private static final int MESSAGE_COUNT = 100;

private final String kerberosContainer;

public KerberosListenerTest(String kerberosContainer) {
this.kerberosContainer = kerberosContainer;
}

public void doTests() throws Exception {

File keyTab = new File("../docker/kerberos/keys/kafka_client.keytab");
File keyTab = new File("target/kafka_client.keytab");
TestUtil.copyFileFromContainer(kerberosContainer, "/keytabs/kafka_client.keytab", keyTab.getAbsolutePath());
Assert.assertTrue(keyTab.exists());
Assert.assertTrue(keyTab.canRead());

Properties props = new Properties();
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.kerberos.service.name", "kafka");
props.put("sasl.jaas.config", "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab='../docker/kerberos/keys/kafka_client.keytab' principal='kafka/client@KERBEROS';");
props.put("sasl.jaas.config", "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true storeKey=true keyTab='" +
keyTab.getAbsolutePath() + "' principal='kafka/client@KERBEROS';");
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9099");

Admin admin = Admin.create(props);
Expand Down
Loading
Loading