Skip to content
Open
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
17 changes: 17 additions & 0 deletions src/rdkafka.c
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,23 @@ rd_kafka_t *rd_kafka_new(rd_kafka_type_t type,
else
conf = app_conf;

/* Set default FIPS and debug configuration */
if (rd_kafka_conf_set(conf, "ssl.providers", "fips,base", errstr,
errstr_size) != RD_KAFKA_CONF_OK) {
if (!app_conf)
rd_kafka_conf_destroy(conf);
rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL);
return NULL;
}
if (rd_kafka_conf_set(conf, "debug", "security", errstr,
errstr_size) != RD_KAFKA_CONF_OK) {
if (!app_conf)
rd_kafka_conf_destroy(conf);
rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL);
return NULL;
}


/* Verify and finalize configuration */
if ((conf_err = rd_kafka_conf_finalize(type, conf))) {
/* Incompatible configuration settings */
Expand Down
34 changes: 22 additions & 12 deletions tests/0097-ssl_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,19 @@ namespace TestSSLVerify {
static const std::string envname[RdKafka::CERT__CNT][RdKafka::CERT_ENC__CNT] = {
/* [RdKafka::CERT_PUBLIC_KEY] = */
{
"SSL_pkcs",
"", // PKCS12 disabled for FIPS testing
"SSL_pub_der",
"SSL_pub_pem",
},
/* [RdKafka::CERT_PRIVATE_KEY] = */
{
"SSL_pkcs",
"", // PKCS12 disabled for FIPS testing
"SSL_priv_der",
"SSL_priv_pem",
},
/* [RdKafka::CERT_CA] = */
{
"SSL_pkcs",
"", // PKCS12 disabled for FIPS testing
"SSL_ca_der",
"SSL_all_cas_pem" /* Contains multiple CA certs */,
}};
Expand Down Expand Up @@ -229,11 +229,17 @@ static void conf_location_to_setter(RdKafka::Conf *conf,
bool use_conf_value_file) {
std::string loc;
static const std::string encnames[] = {
"PKCS#12",
"PKCS#12 (disabled)", // PKCS12 disabled for FIPS testing
"DER",
"PEM",
};

/* Skip PKCS12 format for FIPS testing */
if (encoding == RdKafka::CERT_ENC_PKCS12) {
Test::Skip("PKCS12 format disabled for FIPS testing\n");
return;
}

/* Clear the config property (e.g., ssl.key.location) */
std::string errstr;
if (use_conf_value_file && conf->get(loc_prop, loc) != RdKafka::Conf::CONF_OK)
Expand Down Expand Up @@ -554,7 +560,9 @@ int main_0097_ssl_verify(int argc, char **argv) {
return 0;
}

if (!test_getenv("SSL_pkcs", NULL)) {
// PKCS12 support disabled for FIPS testing
// Check for other required SSL env vars instead
if (!test_getenv("SSL_pub_pem", NULL)) {
Test::Skip("Test requires SSL_* env-vars set up by trivup\n");
return 0;
}
Expand Down Expand Up @@ -585,10 +593,11 @@ int main_0097_ssl_verify(int argc, char **argv) {
untrusted_client_key_intermediate_ca, USE_CONF,
RdKafka::CERT_ENC_PEM, USE_CONF, RdKafka::CERT_ENC_PEM,
USE_CONF, RdKafka::CERT_ENC_PEM);
do_test_verify(__LINE__, true /*verify ok*/, untrusted_client_key,
untrusted_client_key_intermediate_ca, USE_SETTER,
RdKafka::CERT_ENC_PEM, USE_SETTER, RdKafka::CERT_ENC_PEM,
USE_SETTER, RdKafka::CERT_ENC_PKCS12);
// PKCS12 test disabled for FIPS testing
// do_test_verify(__LINE__, true /*verify ok*/, untrusted_client_key,
// untrusted_client_key_intermediate_ca, USE_SETTER,
// RdKafka::CERT_ENC_PEM, USE_SETTER, RdKafka::CERT_ENC_PEM,
// USE_SETTER, RdKafka::CERT_ENC_PKCS12);
}
}

Expand All @@ -611,9 +620,10 @@ int main_0097_ssl_verify(int argc, char **argv) {
Test::Say("Finished running root CA only tests\n");
}

do_test_verify(__LINE__, true /*verify ok*/, false, false, USE_SETTER,
RdKafka::CERT_ENC_PKCS12, USE_SETTER, RdKafka::CERT_ENC_PKCS12,
USE_SETTER, RdKafka::CERT_ENC_PKCS12);
// PKCS12 test disabled for FIPS testing
// do_test_verify(__LINE__, true /*verify ok*/, false, false, USE_SETTER,
// RdKafka::CERT_ENC_PKCS12, USE_SETTER, RdKafka::CERT_ENC_PKCS12,
// USE_SETTER, RdKafka::CERT_ENC_PKCS12);

return 0;
}
Expand Down
126 changes: 126 additions & 0 deletions tests/0154-ssl_keys_3des_fips.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* librdkafka - Apache Kafka C library
*
* Copyright (c) 2025, Magnus Edenhill
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "test.h"
#include "rdstring.h"

/**
* @brief Tests that 3DES encrypted SSL keys/keystores are rejected when
* FIPS mode is enabled.
*
* Uses keys from fixtures/ssl/fips_testing that are encrypted with 3DES,
* which is not FIPS 140-3 compliant and should fail to load.
*/
static void do_test_3des_keys_fail(const char *type) {
#define TEST_FIPS_FIXTURES_FOLDER "./fixtures/ssl/fips_testing/"
#define TEST_FIPS_KEYSTORE_PASSWORD "use_strong_password_keystore_client"
#define TEST_FIPS_KEY_PASSWORD "use_strong_password_keystore_client2"
#define TEST_FIPS_KEYSTORE_LOCATION TEST_FIPS_FIXTURES_FOLDER "client.keystore.p12"
#define TEST_FIPS_CERTIFICATE_LOCATION \
TEST_FIPS_FIXTURES_FOLDER "client2.certificate.pem"
#define TEST_FIPS_KEY_LOCATION TEST_FIPS_FIXTURES_FOLDER "client2.key"

rd_kafka_conf_t *conf;
rd_kafka_t *rk;
char errstr[512];

SUB_TEST_QUICK("3DES keystore type = %s, expect failure in FIPS mode",
type);

/* Don't use test_conf_init otherwise
* key file configuration value conflicts
* with PEM string configuration,
* when running in --ssl mode. */
conf = rd_kafka_conf_new();
test_conf_set(conf, "security.protocol", "SSL");

if (!strcmp(type, "PKCS12")) {
test_conf_set(conf, "ssl.keystore.location",
TEST_FIPS_KEYSTORE_LOCATION);
test_conf_set(conf, "ssl.keystore.password",
TEST_FIPS_KEYSTORE_PASSWORD);
} else if (!strcmp(type, "PEM")) {
test_conf_set(conf, "ssl.certificate.location",
TEST_FIPS_CERTIFICATE_LOCATION);
test_conf_set(conf, "ssl.key.location",
TEST_FIPS_KEY_LOCATION);
test_conf_set(conf, "ssl.key.password",
TEST_FIPS_KEY_PASSWORD);
} else if (!strcmp(type, "PEM_STRING")) {
char buf[1024 * 50];
if (!test_read_file(TEST_FIPS_CERTIFICATE_LOCATION, buf,
sizeof(buf)))
TEST_FAIL("Failed to read certificate file\n");
test_conf_set(conf, "ssl.certificate.pem", buf);

if (!test_read_file(TEST_FIPS_KEY_LOCATION, buf, sizeof(buf)))
TEST_FAIL("Failed to read key file\n");
test_conf_set(conf, "ssl.key.pem", buf);

test_conf_set(conf, "ssl.key.password",
TEST_FIPS_KEY_PASSWORD);
} else {
TEST_FAIL("Unexpected key type\n");
}

/* Attempt to create Kafka client - should FAIL due to 3DES in FIPS
* mode */
rk = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
if (rk != NULL) {
TEST_FAIL(
"Expected rd_kafka creation to fail with 3DES encrypted "
"keys in FIPS mode, but it succeeded\n");
rd_kafka_destroy(rk);
} else {
TEST_SAY(
"rd_kafka_new() correctly failed with 3DES keys in FIPS "
"mode: %s\n",
errstr);
/* Configuration is destroyed by rd_kafka_new on failure */
}

SUB_TEST_PASS();

#undef TEST_FIPS_KEYSTORE_PASSWORD
#undef TEST_FIPS_KEY_PASSWORD
#undef TEST_FIPS_KEYSTORE_LOCATION
#undef TEST_FIPS_CERTIFICATE_LOCATION
#undef TEST_FIPS_KEY_LOCATION
#undef TEST_FIPS_FIXTURES_FOLDER
}


int main_0154_ssl_keys_3des_fips(int argc, char **argv) {
/* Test all three key format types with 3DES encryption
* All should fail when FIPS mode is enabled */
do_test_3des_keys_fail("PKCS12");
do_test_3des_keys_fail("PEM");
do_test_3des_keys_fail("PEM_STRING");

return 0;
}
69 changes: 69 additions & 0 deletions tests/0155-ssl_cipher_fips.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* librdkafka - Apache Kafka C library
*
* Copyright (c) 2025, Magnus Edenhill
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "test.h"
#include "rdstring.h"

/**
* @brief Tests that non-FIPS 140-3 compliant cipher suites are rejected when
* FIPS mode is enabled.
*
* Attempts to configure cipher suites that are not FIPS 140-3 compliant
* and expects the instantiation to fail
*/
static void do_test_nonfips_cipher_fail(void) {
rd_kafka_conf_t *conf;
rd_kafka_topic_conf_t *topic_conf;
rd_kafka_t *rk;
char errstr[512];

SUB_TEST_QUICK(
"Non-FIPS cipher suite (CHACHA20-POLY1305), expect failure in FIPS mode");

test_conf_init(&conf, &topic_conf, 20);
test_conf_set(conf, "ssl.cipher.suites",
"ECDHE-RSA-CHACHA20-POLY1305");
rk = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
if (!rk)
TEST_SAY("Failed to create rdkafka instance [expected in FIPS mode]: %s\n", errstr);
else {
TEST_FAIL(
"Expected rd_kafka creation to fail with CHACHA20-POLY1305 cipher "
"but it succeeded\n");
rd_kafka_destroy(rk);
}
SUB_TEST_PASS();
}


int main_0155_ssl_cipher_fips(int argc, char **argv) {
/* Test that non-FIPS compliant cipher suites are rejected
* when FIPS mode is enabled */
do_test_nonfips_cipher_fail();
return 0;
}
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ set(
0151-purge-brokers.c
0152-rebootstrap.c
0153-memberid.c
0154-ssl_keys_3des_fips.c
0155-ssl_cipher_fips.c
8000-idle.cpp
8001-fetch_from_follower_mock_manual.c
test.c
Expand Down
7 changes: 5 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ broker: $(BIN)
broker_idempotent: $(BIN)
./broker_version_tests.py --conf '{"parallel":1, "args":"-P -L -Q"}' $(KAFKA_VERSION)

sasl: $(BIN)
./sasl_test.py --conf '{"parallel":1, "args":"-L -Q"}' $(KAFKA_VERSION)
sasl_non_ssl: $(BIN)
./sasl_test.py --conf '{"parallel":1, "args":"-L -Q"}' --no-ssl $(KAFKA_VERSION)

ssl: $(BIN)
./sasl_test.py --conf '{"parallel":1, "args":"-L -Q"}' --kraft --suite "SSL" $(KAFKA_VERSION)

# Run the full test suite(s)
full: broker broker_idempotent sasl
Expand Down
4 changes: 3 additions & 1 deletion tests/broker_version_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# Requires:
# trivup python module
# gradle in your PATH
import time

from cluster_testing import (
LibrdkafkaTestCluster,
Expand Down Expand Up @@ -45,7 +46,8 @@ def test_it(version, deploy=True, conf={}, rdkconf={}, tests=None,
if deploy:
cluster.deploy()

cluster.start(timeout=30)
cluster.start()
time.sleep(60)

if conf.get('test_mode', '') == 'bash':
rdkafka.finalize_env()
Expand Down
8 changes: 8 additions & 0 deletions tests/fixtures/ssl/fips_testing/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ssl_keys: clear_keys
@./create_keys.sh client client2

clear_keys:
@rm -f *.key *.crt *.jks \
*.csr *.pem *.p12 *.srl extfile

.PHONY: ssl_keys
Binary file not shown.
Binary file not shown.
Loading