Skip to content

Commit

Permalink
[ST] Remove SecurityST#testCertificates (#10830)
Browse files Browse the repository at this point in the history
Signed-off-by: Lukas Kral <lukywill16@gmail.com>
  • Loading branch information
im-konge authored Nov 14, 2024
1 parent 82a2171 commit 686bbed
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,67 +22,19 @@
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;

import static io.strimzi.systemtest.security.SystemTestCertAndKeyBuilder.endEntityCertBuilder;
import static io.strimzi.systemtest.security.SystemTestCertAndKeyBuilder.intermediateCaCertBuilder;
import static io.strimzi.systemtest.security.SystemTestCertAndKeyBuilder.rootCaCertBuilder;
import static io.strimzi.systemtest.security.SystemTestCertAndKeyBuilder.strimziCaCertBuilder;
import static io.strimzi.test.k8s.KubeClusterResource.cmdKubeClient;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.asList;

public class SystemTestCertManager {

private static final String KAFKA_CERT_FILE_PATH = "/opt/kafka/broker-certs/";
private static final String ZK_CERT_FILE_PATH = "/opt/kafka/zookeeper-node-certs/";
private static final String CA_FILE_PATH = "/opt/kafka/cluster-ca-certs/ca.crt";
static final String STRIMZI_ROOT_CA = "C=CZ, L=Prague, O=Strimzi, CN=StrimziRootCA";
static final String STRIMZI_INTERMEDIATE_CA = "C=CZ, L=Prague, O=Strimzi, CN=StrimziIntermediateCA";
static final String STRIMZI_END_SUBJECT = "C=CZ, L=Prague, O=Strimzi, CN=kafka.strimzi.io";

private static List<String> generateBaseSSLCommand(String server, String caFilePath, String hostname) {
return new ArrayList<>(asList("echo -n | openssl",
"s_client",
"-connect", server,
"-showcerts",
"-CAfile", caFilePath,
"-verify_hostname", hostname
));
}

public static String generateOpenSslCommandByComponentUsingSvcHostname(String namespaceName, String podName, String hostname, String port, String component) {
return generateOpenSslCommandByComponent(namespaceName, podName + "." + hostname + ":" + port,
podName + "." + hostname + "." + namespaceName + ".svc.cluster.local", podName, component, true);
}

public static String generateOpenSslCommandByComponent(String namespaceName, String server, String hostname, String podName, String component) {
return generateOpenSslCommandByComponent(namespaceName, server, hostname, podName, component, true);
}

public static String generateOpenSslCommandByComponent(String namespaceName, String server, String hostname, String podName, String component, boolean withCertAndKey) {
String path = component.equals("kafka") ? KAFKA_CERT_FILE_PATH : ZK_CERT_FILE_PATH;
List<String> cmd = generateBaseSSLCommand(server, CA_FILE_PATH, hostname);

if (withCertAndKey) {
cmd.add("-cert " + path + podName + ".crt");
cmd.add("-key " + path + podName + ".key");
}

return cmdKubeClient(namespaceName).execInPod(podName, "/bin/bash", "-c", String.join(" ", cmd)).out();
}

public static List<String> getCertificateChain(String certificateName) {
return new ArrayList<>(asList(
"s:O = io.strimzi, CN = " + certificateName + "\n" +
" i:O = io.strimzi, CN = cluster-ca",
"Server certificate\n" +
"subject=O = io.strimzi, CN = " + certificateName + "\n" +
"issuer=O = io.strimzi, CN = cluster-ca"
));
}

public static SystemTestCertAndKey generateRootCaCertAndKey() {
return rootCaCertBuilder()
.withIssuerDn(STRIMZI_ROOT_CA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import io.strimzi.api.kafka.model.connect.KafkaConnect;
import io.strimzi.api.kafka.model.connect.KafkaConnectResources;
import io.strimzi.api.kafka.model.kafka.Kafka;
import io.strimzi.api.kafka.model.kafka.KafkaBuilder;
import io.strimzi.api.kafka.model.kafka.KafkaResources;
import io.strimzi.api.kafka.model.kafka.cruisecontrol.CruiseControlResources;
import io.strimzi.api.kafka.model.kafka.exporter.KafkaExporterResources;
Expand Down Expand Up @@ -72,15 +71,13 @@
import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static io.strimzi.api.kafka.model.kafka.KafkaResources.clientsCaCertificateSecretName;
import static io.strimzi.api.kafka.model.kafka.KafkaResources.clientsCaKeySecretName;
Expand All @@ -103,111 +100,13 @@
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Tag(REGRESSION)
class SecurityST extends AbstractST {

private static final Logger LOGGER = LogManager.getLogger(SecurityST.class);
private static final String OPENSSL_RETURN_CODE = "Verify return code: 0 (ok)";

@ParallelNamespaceTest
void testCertificates() {
final TestStorage testStorage = new TestStorage(ResourceManager.getTestContext());

LOGGER.info("Running testCertificates {}", testStorage.getClusterName());

resourceManager.createResourceWithWait(
NodePoolsConverter.convertNodePoolsIfNeeded(
KafkaNodePoolTemplates.brokerPoolPersistentStorage(testStorage.getNamespaceName(), testStorage.getBrokerPoolName(), testStorage.getClusterName(), 3).build(),
KafkaNodePoolTemplates.controllerPoolPersistentStorage(testStorage.getNamespaceName(), testStorage.getControllerPoolName(), testStorage.getClusterName(), 3).build()
)
);

KafkaBuilder kafkaBuilder = KafkaTemplates.kafkaEphemeral(testStorage.getNamespaceName(), testStorage.getClusterName(), 3);

if (!Environment.isKRaftModeEnabled()) {
// in order to make the connection work on FIPS-enabled cluster, we need to enable TLSv1.3 on the ZooKeeper side
// Note, this cipherSuites comes from ZK master branch, where some cipher suites are missing in v3.8.4 branch:
// https://github.com/apache/zookeeper/blob/837f86cc713a5e4ce56e1f75eeb335093ca18821/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java#L142
String tlsV13CipherSuites = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256," +
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256," +
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA," +
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," +
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256";

kafkaBuilder = kafkaBuilder
.editSpec()
.editOrNewZookeeper()
.addToConfig("ssl.protocol", "TLSv1.3")
.addToConfig("ssl.quorum.protocol", "TLSv1.3")
.addToConfig("ssl.enabledProtocols", "TLSv1.3,TLSv1.2")
.addToConfig("ssl.quorum.enabledProtocols", "TLSv1.3,TLSv1.2")
.addToConfig("ssl.ciphersuites", tlsV13CipherSuites)
.addToConfig("ssl.quorum.ciphersuites", tlsV13CipherSuites)
.endZookeeper()
.endSpec();
}

resourceManager.createResourceWithWait(kafkaBuilder.build());

String brokerPodName = kubeClient().listPods(testStorage.getNamespaceName(), testStorage.getBrokerSelector()).get(0).getMetadata().getName();

LOGGER.info("Check Kafka bootstrap certificate");
String outputCertificate = SystemTestCertManager.generateOpenSslCommandByComponent(testStorage.getNamespaceName(), KafkaResources.tlsBootstrapAddress(testStorage.getClusterName()), KafkaResources.bootstrapServiceName(testStorage.getClusterName()),
brokerPodName, "kafka", false);
LOGGER.info("OPENSSL OUTPUT: \n\n{}\n\n", outputCertificate);
verifyCerts(testStorage.getClusterName(), outputCertificate, "kafka");

if (!Environment.isKRaftModeEnabled()) {
LOGGER.info("Check ZooKeeper client certificate");
outputCertificate = SystemTestCertManager.generateOpenSslCommandByComponent(testStorage.getNamespaceName(), KafkaResources.zookeeperServiceName(testStorage.getClusterName()) + ":2181", KafkaResources.zookeeperServiceName(testStorage.getClusterName()),
brokerPodName, "kafka");
verifyCerts(testStorage.getClusterName(), outputCertificate, "zookeeper");
}

List<String> kafkaPorts = new ArrayList<>(Arrays.asList("9091", "9093"));
List<String> zkPorts = new ArrayList<>(Arrays.asList("2181", "3888"));
List<String> brokerPods = kubeClient().listPodNames(testStorage.getNamespaceName(), testStorage.getBrokerSelector());

brokerPods.forEach(brokerPod -> {
String output;

LOGGER.info("Checking certificates for {}", brokerPod);
for (String kafkaPort : kafkaPorts) {
LOGGER.info("Check Kafka certificate for port {}", kafkaPort);
output = SystemTestCertManager.generateOpenSslCommandByComponentUsingSvcHostname(testStorage.getNamespaceName(),
brokerPod,
KafkaResources.brokersServiceName(testStorage.getClusterName()), kafkaPort, "kafka");
verifyCerts(testStorage.getClusterName(), output, "kafka");
}
});

IntStream.rangeClosed(0, 2).forEach(podId -> {
String output;

if (!Environment.isKRaftModeEnabled()) {
for (String zkPort : zkPorts) {
LOGGER.info("Check ZooKeeper certificate for port {}", zkPort);
output = SystemTestCertManager.generateOpenSslCommandByComponentUsingSvcHostname(testStorage.getNamespaceName(), KafkaResources.zookeeperPodName(testStorage.getClusterName(), podId),
KafkaResources.zookeeperHeadlessServiceName(testStorage.getClusterName()), zkPort, "zookeeper");
verifyCerts(testStorage.getClusterName(), output, "zookeeper");
}
}
});
}

// synchronized avoiding data-race (list of string is allocated on the heap), but has different reference on stack it's ok
// but Strings parameters provided are not created in scope of this method
synchronized private static void verifyCerts(String clusterName, String certificate, String component) {
List<String> certificateChains = SystemTestCertManager.getCertificateChain(clusterName + "-" + component);

assertThat(certificate, containsString(certificateChains.get(0)));
assertThat(certificate, containsString(certificateChains.get(1)));
assertThat(certificate, containsString(OPENSSL_RETURN_CODE));
}

@ParallelNamespaceTest
@Tag(ROLLING_UPDATE)
Expand Down

0 comments on commit 686bbed

Please sign in to comment.