diff --git a/include/fluent-bit/flb_input.h b/include/fluent-bit/flb_input.h index 0f59bc9189a..b7f4d122803 100644 --- a/include/fluent-bit/flb_input.h +++ b/include/fluent-bit/flb_input.h @@ -510,6 +510,7 @@ struct flb_input_instance { char *tls_crt_file; /* Certificate */ char *tls_key_file; /* Cert Key */ char *tls_key_passwd; /* Cert Key Password */ + char *tls_crl_file; /* Certificate Revocation List */ char *tls_min_version; /* Minimum protocol version of TLS */ char *tls_max_version; /* Maximum protocol version of TLS */ char *tls_ciphers; /* TLS ciphers */ diff --git a/include/fluent-bit/flb_output.h b/include/fluent-bit/flb_output.h index 08eced889dc..4b1e5430361 100644 --- a/include/fluent-bit/flb_output.h +++ b/include/fluent-bit/flb_output.h @@ -387,6 +387,7 @@ struct flb_output_instance { char *tls_crt_file; /* Certificate */ char *tls_key_file; /* Cert Key */ char *tls_key_passwd; /* Cert Key Password */ + char *tls_crl_file; /* Certificate Revocation List */ char *tls_min_version; /* Minimum protocol version of TLS */ char *tls_max_version; /* Maximum protocol version of TLS */ char *tls_ciphers; /* TLS ciphers */ diff --git a/include/fluent-bit/tls/flb_tls.h b/include/fluent-bit/tls/flb_tls.h index 3d4c482a602..624e4a132e4 100644 --- a/include/fluent-bit/tls/flb_tls.h +++ b/include/fluent-bit/tls/flb_tls.h @@ -95,6 +95,7 @@ struct flb_tls_backend { /* Additional settings */ int (*context_alpn_set) (void *, const char *); int (*context_set_verify_client) (void *, int); + int (*context_set_crl_file) (void *, const char *); /* TLS Protocol version */ int (*set_minmax_proto) (struct flb_tls *tls, const char *, const char *); @@ -139,6 +140,7 @@ struct flb_tls { char *crt_file; /* Certificate */ char *key_file; /* Cert Key */ char *key_passwd; /* Cert Key Password */ + char *crl_file; /* Certificate revocation list */ char *alpn; /* ALPN protocol list */ char *min_version; /* Minimum TLS version */ char *max_version; /* Maximum TLS version */ @@ -178,6 +180,7 @@ int flb_tls_reload_if_needed(struct flb_tls *tls); int flb_tls_set_alpn(struct flb_tls *tls, const char *alpn); int flb_tls_set_verify_client(struct flb_tls *tls, int verify_client); +int flb_tls_set_crl_file(struct flb_tls *tls, const char *crl_file); int flb_tls_set_verify_hostname(struct flb_tls *tls, int verify_hostname); #if defined(FLB_SYSTEM_WINDOWS) diff --git a/src/flb_input.c b/src/flb_input.c index b7010a6ac6c..226062d1370 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -618,6 +618,7 @@ struct flb_input_instance *flb_input_new(struct flb_config *config, instance->tls_crt_file = NULL; instance->tls_key_file = NULL; instance->tls_key_passwd = NULL; + instance->tls_crl_file = NULL; #endif /* Plugin requires a co-routine context ? */ @@ -952,6 +953,9 @@ int flb_input_set_property(struct flb_input_instance *ins, else if (prop_key_check("tls.key_passwd", k, len) == 0) { flb_utils_set_plugin_string_property("tls.key_passwd", &ins->tls_key_passwd, tmp); } + else if (prop_key_check("tls.crl_file", k, len) == 0) { + flb_utils_set_plugin_string_property("tls.crl_file", &ins->tls_crl_file, tmp); + } else if (prop_key_check("tls.min_version", k, len) == 0) { flb_utils_set_plugin_string_property("tls.min_version", &ins->tls_min_version, tmp); } @@ -1208,6 +1212,10 @@ void flb_input_instance_destroy(struct flb_input_instance *ins) flb_sds_destroy(ins->tls_key_file); } + if (ins->tls_crl_file) { + flb_sds_destroy(ins->tls_crl_file); + } + if (ins->tls_key_passwd) { flb_sds_destroy(ins->tls_key_passwd); } @@ -1920,6 +1928,16 @@ int flb_input_instance_init(struct flb_input_instance *ins, return -1; } } + + if (ins->tls_crl_file != NULL) { + ret = flb_tls_set_crl_file(ins->tls, ins->tls_crl_file); + if (ret != 0) { + flb_error("[input %s] error setting up TLS CRL file", + ins->name); + + return -1; + } + } } struct flb_config_map *m; diff --git a/src/flb_output.c b/src/flb_output.c index 42a3f2b04d3..79ff8faf255 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -191,6 +191,9 @@ static void flb_output_free_properties(struct flb_output_instance *ins) if (ins->tls_key_passwd) { flb_sds_destroy(ins->tls_key_passwd); } + if (ins->tls_crl_file) { + flb_sds_destroy(ins->tls_crl_file); + } if (ins->tls_min_version) { flb_sds_destroy(ins->tls_min_version); } @@ -850,6 +853,7 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, instance->tls_crt_file = NULL; instance->tls_key_file = NULL; instance->tls_key_passwd = NULL; + instance->tls_crl_file = NULL; # if defined(FLB_SYSTEM_WINDOWS) instance->tls_win_certstore_name = NULL; instance->tls_win_use_enterprise_certstore = FLB_FALSE; @@ -1115,6 +1119,9 @@ int flb_output_set_property(struct flb_output_instance *ins, else if (prop_key_check("tls.key_passwd", k, len) == 0) { flb_utils_set_plugin_string_property("tls.key_passwd", &ins->tls_key_passwd, tmp); } + else if (prop_key_check("tls.crl_file", k, len) == 0) { + flb_utils_set_plugin_string_property("tls.crl_file", &ins->tls_crl_file, tmp); + } else if (prop_key_check("tls.min_version", k, len) == 0) { flb_utils_set_plugin_string_property("tls.min_version", &ins->tls_min_version, tmp); } @@ -1691,6 +1698,16 @@ int flb_output_init_all(struct flb_config *config) } } + if (ins->tls_crl_file != NULL) { + ret = flb_tls_set_crl_file(ins->tls, ins->tls_crl_file); + if (ret != 0) { + flb_error("[output %s] error setting up TLS CRL file", + ins->name); + flb_output_instance_destroy(ins); + return -1; + } + } + # if defined (FLB_SYSTEM_WINDOWS) if (ins->tls_win_use_enterprise_certstore) { ret = flb_tls_set_use_enterprise_store(ins->tls, ins->tls_win_use_enterprise_certstore); diff --git a/src/tls/flb_tls.c b/src/tls/flb_tls.c index 808134e9eaf..c2672dd65ae 100644 --- a/src/tls/flb_tls.c +++ b/src/tls/flb_tls.c @@ -76,6 +76,12 @@ struct flb_config_map tls_configmap[] = { "Optional password for tls.key_file file" }, + { + FLB_CONFIG_MAP_STR, "tls.crl_file", NULL, + 0, FLB_FALSE, 0, + "Absolute path to a Certificate Revocation List (CRL) file in PEM format" + }, + { FLB_CONFIG_MAP_STR, "tls.vhost", NULL, 0, FLB_FALSE, 0, @@ -547,6 +553,9 @@ int flb_tls_destroy(struct flb_tls *tls) if (tls->key_passwd != NULL) { flb_free(tls->key_passwd); } + if (tls->crl_file != NULL) { + flb_free(tls->crl_file); + } if (tls->alpn != NULL) { flb_free(tls->alpn); } @@ -616,6 +625,30 @@ int flb_tls_set_verify_client(struct flb_tls *tls, int verify_client) return 0; } +int flb_tls_set_crl_file(struct flb_tls *tls, const char *crl_file) +{ + int ret; + + if (!tls) { + return -1; + } + + if (tls->ctx && tls->api->context_set_crl_file) { + ret = tls->api->context_set_crl_file(tls->ctx, crl_file); + if (ret != 0) { + return ret; + } + + if (tls_store_string(&tls->crl_file, crl_file) != 0) { + return -1; + } + + return ret; + } + + return 0; +} + int flb_tls_set_verify_hostname(struct flb_tls *tls, int verify_hostname) { if (!tls) { diff --git a/src/tls/openssl.c b/src/tls/openssl.c index 15c8c88f66b..d3c0fb70fd3 100644 --- a/src/tls/openssl.c +++ b/src/tls/openssl.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef FLB_SYSTEM_MACOS #include @@ -456,6 +457,74 @@ static int tls_context_set_verify_client(void *ctx_backend, int verify_client) return 0; } +static int tls_context_set_crl_file(void *ctx_backend, const char *crl_file) +{ + struct tls_context *ctx = ctx_backend; + X509_STORE *store; + X509_CRL *crl; + BIO *bio; + char err_buf[256]; + int loaded = 0; + + if (crl_file == NULL) { + return 0; + } + + pthread_mutex_lock(&ctx->mutex); + + store = SSL_CTX_get_cert_store(ctx->ctx); + if (store == NULL) { + flb_error("[tls] could not retrieve certificate store for CRL"); + pthread_mutex_unlock(&ctx->mutex); + return -1; + } + + bio = BIO_new_file(crl_file, "r"); + if (bio == NULL) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] crl_file '%s': %s", crl_file, err_buf); + pthread_mutex_unlock(&ctx->mutex); + return -1; + } + + while ((crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) != NULL) { + if (X509_STORE_add_crl(store, crl) != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_warn("[tls] could not add CRL from '%s': %s", crl_file, err_buf); + } + else { + loaded++; + } + X509_CRL_free(crl); + } + BIO_free(bio); + + /* PEM_read_bio_X509_CRL leaves a benign EOF error on the stack */ + ERR_clear_error(); + + if (loaded == 0) { + flb_error("[tls] no CRL entries loaded from '%s'", crl_file); + pthread_mutex_unlock(&ctx->mutex); + return -1; + } + + if (X509_STORE_set_flags(store, + X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL) != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] could not enable CRL checking for '%s': %s", + crl_file, err_buf); + pthread_mutex_unlock(&ctx->mutex); + return -1; + } + + pthread_mutex_unlock(&ctx->mutex); + + flb_debug("[tls] loaded %i CRL entrie(s) from '%s'", loaded, crl_file); + + return 0; +} + #ifdef _MSC_VER /* Parse certstore_name prefix like * @@ -716,7 +785,7 @@ static int windows_load_system_certificates(struct tls_context *ctx) return -1; } - flb_debug("[tls] successfully loaded certificates from windows system %s store.", + flb_debug("[tls] successfully loaded certificates from windows system %s store.", configured_name); return 0; } @@ -1251,7 +1320,7 @@ static unsigned char *hex_to_bytes(const char *hex, size_t *out_len) { return buf; } -static int windows_set_allowed_thumbprints(struct tls_context *ctx, const char *thumbprints) +static int windows_set_allowed_thumbprints(struct tls_context *ctx, const char *thumbprints) { char *token_ctx = NULL, *tok = NULL; size_t cap = 4, count = 0; @@ -1387,6 +1456,12 @@ static int tls_context_reload(struct flb_tls *tls) return -1; } + if (tls->crl_file != NULL && + tls_context_set_crl_file(new_ctx, tls->crl_file) != 0) { + tls_context_destroy(new_ctx); + return -1; + } + #if defined(FLB_SYSTEM_WINDOWS) if (tls->certstore_name != NULL && tls_set_certstore_name(&tmp_tls, tls->certstore_name) != 0) { @@ -1973,6 +2048,7 @@ static struct flb_tls_backend tls_openssl = { .context_destroy = tls_context_destroy, .context_alpn_set = tls_context_alpn_set, .context_set_verify_client = tls_context_set_verify_client, + .context_set_crl_file = tls_context_set_crl_file, .session_alpn_get = tls_session_alpn_get, .set_minmax_proto = tls_set_minmax_proto, .set_ciphers = tls_set_ciphers, diff --git a/tests/internal/upstream_tls.c b/tests/internal/upstream_tls.c index b1f689af843..b796a867236 100644 --- a/tests/internal/upstream_tls.c +++ b/tests/internal/upstream_tls.c @@ -478,6 +478,136 @@ void test_tls_reload_does_not_hide_concurrent_file_change(void) flb_free(dst_key); } +void test_tls_reload_reapplies_crl_file(void) +{ + char src_crt[4096]; + char src_key[4096]; + char *dst_crt; + char *dst_key; + struct flb_tls *tls; + + snprintf(src_crt, sizeof(src_crt), "%sdata/tls/certificate.pem", + FLB_TESTS_DATA_PATH); + snprintf(src_key, sizeof(src_key), "%sdata/tls/private_key.pem", + FLB_TESTS_DATA_PATH); + + dst_crt = flb_test_tmpdir_cat("/flb_tls_crl_reload_certificate.pem"); + dst_key = flb_test_tmpdir_cat("/flb_tls_crl_reload_private_key.pem"); + TEST_CHECK(dst_crt != NULL); + TEST_CHECK(dst_key != NULL); + + TEST_CHECK(copy_file(src_crt, dst_crt) == 0); + TEST_CHECK(copy_file(src_key, dst_key) == 0); + + tls = flb_tls_create(FLB_TLS_SERVER_MODE, + FLB_TRUE, + 0, + NULL, + NULL, + NULL, + dst_crt, + dst_key, + NULL); + TEST_CHECK(tls != NULL); + + /* + * A missing stored CRL makes reapplication observable: the reload must + * fail instead of silently replacing the context without CRL checking. + */ + tls->crl_file = flb_strdup("/nonexistent/fluent-bit-crl.pem"); + TEST_CHECK(tls->crl_file != NULL); + + TEST_CHECK(append_file(dst_key, "\n") == 0); + TEST_CHECK(flb_tls_reload_if_needed(tls) == -1); + + flb_tls_destroy(tls); + remove(dst_crt); + remove(dst_key); + flb_free(dst_crt); + flb_free(dst_key); +} + +/* + * CRL (tls.crl_file) dispatch. These use a mock TLS backend (same approach as + * the session tests above) to exercise the flb_tls_set_crl_file() wrapper + * without any real OpenSSL context, certificates or network I/O. + */ +struct crl_mock_ctx { + int calls; + int ret; /* value the mock returns */ +}; + +static const char *crl_mock_last_path; + +static int crl_mock_set_crl_file(void *ctx_backend, const char *crl_file) +{ + struct crl_mock_ctx *m = ctx_backend; + + m->calls++; + crl_mock_last_path = crl_file; /* wrapper forwards the pointer as-is */ + + return m->ret; +} + +/* A NULL tls context must be rejected */ +void test_crl_set_null_tls(void) +{ + TEST_CHECK(flb_tls_set_crl_file(NULL, "x.pem") == -1); +} + +/* The wrapper forwards ctx + path to the backend and propagates success */ +void test_crl_dispatch_success(void) +{ + struct crl_mock_ctx mock = {0}; + struct flb_tls_backend api = {0}; + struct flb_tls tls = {0}; + const char *path = "/etc/crl.pem"; + + mock.ret = 0; + api.context_set_crl_file = crl_mock_set_crl_file; + tls.api = &api; + tls.ctx = &mock; + crl_mock_last_path = NULL; + + TEST_CHECK(flb_tls_set_crl_file(&tls, path) == 0); + TEST_CHECK(mock.calls == 1); + TEST_CHECK(crl_mock_last_path == path); + TEST_CHECK(tls.crl_file != NULL); + TEST_CHECK(tls.crl_file != path); + TEST_CHECK(strcmp(tls.crl_file, path) == 0); + + flb_free(tls.crl_file); +} + +/* The wrapper propagates a backend failure */ +void test_crl_dispatch_error(void) +{ + struct crl_mock_ctx mock = {0}; + struct flb_tls_backend api = {0}; + struct flb_tls tls = {0}; + + mock.ret = -1; + api.context_set_crl_file = crl_mock_set_crl_file; + tls.api = &api; + tls.ctx = &mock; + + TEST_CHECK(flb_tls_set_crl_file(&tls, "/bad.pem") == -1); + TEST_CHECK(mock.calls == 1); +} + +/* A backend without CRL support is a graceful no-op (backend not called) */ +void test_crl_dispatch_unsupported(void) +{ + struct crl_mock_ctx mock = {0}; + struct flb_tls_backend api = {0}; /* context_set_crl_file stays NULL */ + struct flb_tls tls = {0}; + + tls.api = &api; + tls.ctx = &mock; + + TEST_CHECK(flb_tls_set_crl_file(&tls, "/whatever.pem") == 0); + TEST_CHECK(mock.calls == 0); +} /* * Verify that flb_upstream_proxy_tls_setup() is a safe no-op when the * upstream has no HTTPS proxy in effect (proxy_tls_context == NULL). @@ -1206,6 +1336,11 @@ TEST_LIST = { #endif {"tls_reload_does_not_hide_concurrent_file_change", test_tls_reload_does_not_hide_concurrent_file_change}, + {"tls_reload_reapplies_crl_file", test_tls_reload_reapplies_crl_file}, + {"crl_set_null_tls", test_crl_set_null_tls}, + {"crl_dispatch_success", test_crl_dispatch_success}, + {"crl_dispatch_error", test_crl_dispatch_error}, + {"crl_dispatch_unsupported", test_crl_dispatch_unsupported}, {"upstream_proxy_tls_setup_noop_without_proxy", test_upstream_proxy_tls_setup_noop_without_proxy}, {"upstream_proxy_tls_setup_configures_ca", test_upstream_proxy_tls_setup_configures_ca}, {"output_proxy_tls_ca_check", test_output_proxy_tls_ca_check}, diff --git a/tests/runtime/data/tls/ca_certificate.pem b/tests/runtime/data/tls/ca_certificate.pem new file mode 100644 index 00000000000..c0532dedba0 --- /dev/null +++ b/tests/runtime/data/tls/ca_certificate.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFDTCCAvWgAwIBAgIUObKqIDoYgf674IVD15cdfdGaVHcwDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLTk1YLW1UTFMtQ0EwHhcNMjYwNjE1MDc1MTIwWhcNMjcw +NjE1MDc1MTIwWjAWMRQwEgYDVQQDDAtOTVgtbVRMUy1DQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAK0ysr/tjivpac4laAYBAQpXj2lVUS8l2sqni/LZ +NEwDJ76K4OLyG9t1eAEkdLG230cn8+MC5y+oj3i1+Vu7QjO1o2K2nvktXxpLJtNA +qGeqFZDpAH1HPHVPyJ7vKcC49gRFsvgbzAbiAL5SVobVF9En2HMTapPQRKdD6OhB +gjRqZaYZnK5ECWLgDNv0Rz6M3CO3rWDY+znshdUHQIpX6SxjcabVRNS02pfC0SVB +XD77ysJE+SCPrui3hT0sweCgpHX0aE2hzSXVVXgrKVISGYy4swHW1YK5hkRY8+Kt +wPTqBU4G8l7GnEokYtrY1tym9sIdYm5rrFAvqG1Y+/pmanqoVUB2Xv2nX6jPOipy +9R6jnfhZ9O+GA71E1w2U1/6bKtS+Fy4ZLDamAjEz9IojWnX/jeWvlhAF1UVAE5c2 +lYyELSarrQhoKdhkVI1mTzVw+Rvx5dGDL9u4fxOagMMvuk0OH4j1nUliBJ1gj+Kf +VUTb1BCukti5TIOPwH1PkmpI6QVneRGjXpPEjBsvObJ0J/qEkf6+am9x7obijGDw +CFz4//fpjwqAjqc7RAODiNogqkpDsyb2099ddRiVdw44JRHEmJrPI2cTMK4b2IUO +6hn1Vu6nUZhnizb4SF1dYEMTrGFadH6T9G3hc4bjB+yPsJuuaiv/30uTV/ngReew +HXP7AgMBAAGjUzBRMB0GA1UdDgQWBBQGn+YITFaRNj6VoDQQ9aiHlD8s/TAfBgNV +HSMEGDAWgBQGn+YITFaRNj6VoDQQ9aiHlD8s/TAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQAbpLlqLqVRAP1et/gP+RGD4/CIPtaWZwI71FHHrgdE +gfSQOphN6cjfmaYqsV00vwoLHfB6p0k+O1fcTXX2sWldgxXbiCBuKqeB05Qls0+C +RFO7NQPGjMHn3wyltEimKOOCPM2v4HrFqZWMIMU8iJ4o0mSzvHcuz7IsVUYlFd3J +/vHYiULXQMrYQ88+xL5RSdYhSV0yfffIWVY1xto/i7aU/y+cE3Sppk5ZRa6wrnXL +YGcGe37yIKxe0yWo/jHd1qU6wNwm0Ewf7x1og04FiIyAsYhRAV63AeOU88fMtTm/ +PLx3j3KHev08pD+r7cl+r8F6i2o4n4PpuBNBG9zO7KgrKj/XWi0RiG+BnY5+hjRp +HU40GaBAHFR8+yaCM/b2FeBPRsFeFbMMqKHhO4vMAtDcDjawZveqa+b2R0l5EsGG +lTZQLzvB4vSXbGspH+pxcwr4D0tAdleUl49DX1IIAzFgVbXHfAmEmTSn4p6U7WDl +Z8N0qbQns24GgbwKIu22ay//CxkXqXZbrdSqWqx58i+RxC94yKPvwa0Nhgv4LHjm +K5nIGAK3jRK96iia5QprIlRV3GNUW6MlsmOBLxLcfuDLtJXKVf43KJQGFtBNNjIn +NzaeTyrLsp36BwlFcQacJf17zpthrLCileU8K7S+JMIbPbuNkUEKyjTpV+Zm9Up0 +0A== +-----END CERTIFICATE----- diff --git a/tests/runtime/data/tls/client_certificate.pem b/tests/runtime/data/tls/client_certificate.pem new file mode 100644 index 00000000000..2546a39728b --- /dev/null +++ b/tests/runtime/data/tls/client_certificate.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFezCCA2OgAwIBAgIUMHsimGxEDTqZ9az576Nw7Myw3O4wDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLTk1YLW1UTFMtQ0EwHhcNMjYwNjE1MDc1MTIzWhcNMjcw +NjE1MDc1MTIzWjAXMRUwEwYDVQQDDAxzd3gtcHJvdG9uMDQwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQCMeL8wUe8RDGMfABcBdXQUB/ibwPCnIXZdtVjf +86yKIfO/YLMhgt4blNOhgEmiEarAb8o+F7lpu5HAbrN9MbgK0JG6VwMXHNmhmNtx +/h2e5Mocqt1VrcnpGa+eGfRMqYn+uMPTf2k+8X0q1WDJN86N+Mg4qZ8+bcGn8jd3 +3vcAzs4XixuPPatKhE6QFH5NnSyfgnfkA45Q+GjUy5iDIgp+o9I4hSagECEUlxnp +aCe+vUANfjE89D9XOlg+qFOXI509w6FZ6v+vZ0Hdq0GzcYIK2nxT4a2jUzpdYPS0 +pz92erOkJPIh2np42iSEVXMEBg6a3SprXVswuj/YZwEoPKPQ1zffL8iWAhnxgLk0 +2qah5UL29sIE2ecQ7usqTYfe50UpIVNI/ghjfH4w/qX4Ur+Lr5EtBOX3Ax6Atb9U +nU3QrXjxKc8T7c4kBgo+67I7sVz3t9lzMB7N3kJtHqLEernMWJh3nSmBJP/02j53 +kWV5kiC/lo0laypIxrnk1+Ria28k8C/aUIiwNffwQM7LGjF5tr/LkCZ25AECSd6f +9qtNKc1U2k23Afxr/EQ2C7KtwSH+0EnGt9NcaxYSK1gPPA5x6TLXj8dQjtVmKoro +9QspTRyNp+lQgdwWCmXBQMnIrQF/uqPOwgtCgJo/uTaCJzPVVqI9BwqMtfyb4e/S +emZ5AwIDAQABo4G/MIG8MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADBABgNVHREEOTA3ggxzd3gtcHJvdG9u +MDSCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAAYcEAAAAADAdBgNV +HQ4EFgQUAH0Gx96jR8OcDQrSDoU7PBUwz4wwHwYDVR0jBBgwFoAUBp/mCExWkTY+ +laA0EPWoh5Q/LP0wDQYJKoZIhvcNAQELBQADggIBACasduJjq75AUFRraBl2NLcE +TEd2QO5YDIDGaFbKxGHbnIA8t7LXM25tDaOR3CZt/NYJ+7uZKRz84Q0gAeAx/uEY +/2PyJH+65iktC7ZEWr3+S+DrNOg/xjxKxk1mH5khbbDJE9iFZJUnoUPjDDV7r5ia +yS4ineUCu081t6V5I8N+O4PDMKozzzyYw626lfEhFBD1EKjsabe2CCqNJSBaVrpI +e1UdoaOOT3vtPlAQo62GnjB0Kjpliip7EsA6DgxRmatyXSW15wcbLOTxW6fQ5tuB +lm0QhAj3P0cDO/XNlWxHA2WeJXFf23pM2KfzFK8Y2O0l2Ta1M8ngBa0ikmFG6qBT +Ul5Udi5djDEfEAzTHiGqIlyTYL0BKw2l/kb0FLzjsJYO5+SQFfOb9SBTEMT1wOBn +2e5+1nqQewZy52eem1Z1LSpHelBWUyOjG1bf+cfS03b8y7TSwGOrKlVx+0t6O6x0 +1i5ObvoN5BCymLv51QW9nOIVgut04umPJhjs/Iq8/BPEVqs3ACkk14Xf91seUdzZ +BDvaycA00II/m/GOI8HhIccz/zqtiA6v5LNX4LTANE6ea2BhB89jAuSozdf5bQBB +9UgXQQaGwhWvFvJEwb0yOY2p8TI6thmP2U7CjGkHuCcQCdhygilJEECBq0DcjCoI +wfV1480NsYqTC6fixxgB +-----END CERTIFICATE----- diff --git a/tests/runtime/data/tls/client_certificate_revoked.pem b/tests/runtime/data/tls/client_certificate_revoked.pem new file mode 100644 index 00000000000..d8afa90c2be --- /dev/null +++ b/tests/runtime/data/tls/client_certificate_revoked.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFezCCA2OgAwIBAgIULHfQLJx38R+p1MAkGSld/Ir11S8wDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLTk1YLW1UTFMtQ0EwHhcNMjYwNjE1MDc1MTI2WhcNMjcw +NjE1MDc1MTI2WjAXMRUwEwYDVQQDDAxzd3gtcHJvdG9uMDQwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQDBSRlnWgfbauS1TEWS0OJx2PB7TxbSiwzkhhkD +QWlruw9iPAQfFT+rT1/GYuMD6TQ3rEQmsX7CuWgaNt0BeFSxqsQmTCp4JbLfvfRD +Rzz6mHq7aiG+2tpxjBV8or+11Kp3qVjN2h+PcArFaxq8Ola9bUtXpHEZnJCoVLx2 +in4n3e97PQxXE3C2pbBjn7VSjTkw2BJSMgBApP6KH1Q73/ueI4jcWbB4jFveO5xx +h/qs9MKGf9bu//TUEQ9cSEUSl0P3HvnKNmRLOYwioeaoDqNi5TrWc2r0/lcEgGc4 +FnAkAKduqQICOCf8d4cdzhssJMAEK+QsOha5ETRqBzV2suFMvSR+z0HHmrF9duxR +nRbj/H4D6G9Z8/sDVsWaH76zGVRIgX5cgh/14b+PsimYG8sUPWXfZsv6QbOY/sRX +zPKTEi6XlyNgZ6HJaRBy80GqT3PhT2RbNMVcIxshAPm8OMipH6jGRStBNPwLcT1N +a1xROpjLiCDU00HDKdAxLknhAEWTSo+Lr741tzcrjUb6iNatKZUvkPAkvpiVYeTD +bfi4E6Z7OvTedzlT8qKBMEx4oJLWangkVBAyLMr+fiuL3Thz854OHREeqB9QpuV5 +BEKNb9gzXQVni62i3uoAXqk8Ew/KSSK3Wg0+L8nkeNYFyVVS4ywtSEo3TVKqpRuZ +Y0hHhwIDAQABo4G/MIG8MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwCQYDVR0TBAIwADBABgNVHREEOTA3ggxzd3gtcHJvdG9u +MDSCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAAYcEAAAAADAdBgNV +HQ4EFgQUJs+LQq9H4GIOkzMD51y1sGfm1gYwHwYDVR0jBBgwFoAUBp/mCExWkTY+ +laA0EPWoh5Q/LP0wDQYJKoZIhvcNAQELBQADggIBAGlZDR4Y9qejLNiCDkCyJe24 +Hy/6YCzi2QKnRSH7U8V5NL5YvgBQQ5U1y27KL456Hs0sTAak8Iqw826tpUmMcOWh +EVV3qpiNteyt+eEcwNz/bWM2TtzMLtxczUfqokW9CkiC6sObYWjoIvEx8MLFiUqc +6dlpPDM9+KKC+V3CkPn6G4OfqocC7V8+EDrEnR5i7fSSNU9QlpZaATNV6m6THrof +DXKkDBAzBNrRikzQd0mY7R9xJOZz/0Fd13zg5AHYOYh2HYhfwPywbbUklb7FyEET +XVVFpZrjXXdmtd3K/RPb0Snlzsl0WAo1AgYBJsICjhqW2jp7KXAq/466tzj1LCww +426A7bLUjWrAs7i0+7Q/b8fxR3skC3EvYkkdPbWDq9BDInXscC3Uj95zD6/YsVKi +ue8LIBfRHK2FjjVpOVBwedF+0e+ul/uvvYSgisYlUieydLpyeDFzzZOc+im679pn +NryYlbw8mQlM5mNUc5PsqgidcdHM1Nj6rHxCIYX4H5VJHPW8afVDgEoJ59A01K4E +X8SMvrj57Eos7wJFXGPzp7hrXE5QSrcXjT5bgSh2vnpaSVSLJ2mvC07QAaikSF3Y +2xABvwNr5LF8aFNm7NOfKY59lcgP3+XwslQ3qMDVV45NBYBNrjD/WNHjd5i79mIo +ZSShcYXG+QmcJcMQPmrj +-----END CERTIFICATE----- diff --git a/tests/runtime/data/tls/client_private_key.pem b/tests/runtime/data/tls/client_private_key.pem new file mode 100644 index 00000000000..7f47d751c12 --- /dev/null +++ b/tests/runtime/data/tls/client_private_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +H5ib1ozscVnxxTEQA+Mvw4M2/VMy +-----END PRIVATE KEY----- diff --git a/tests/runtime/data/tls/client_private_key_revoked.pem b/tests/runtime/data/tls/client_private_key_revoked.pem new file mode 100644 index 00000000000..1463ed35ae8 --- /dev/null +++ b/tests/runtime/data/tls/client_private_key_revoked.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +OaoQQ17fqhuut3MmtESc664RrdPoPw== +-----END PRIVATE KEY----- diff --git a/tests/runtime/data/tls/crl.pem b/tests/runtime/data/tls/crl.pem new file mode 100644 index 00000000000..14258875a69 --- /dev/null +++ b/tests/runtime/data/tls/crl.pem @@ -0,0 +1,16 @@ +-----BEGIN X509 CRL----- +MIICmDCBgQIBATANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtOTVgtbVRMUy1D +QRcNMjYwNjE1MDc1MTI2WhcNMjcwNjE1MDc1MTI2WjAnMCUCFCx30Cycd/EfqdTA +JBkpXfyK9dUvFw0yNjA2MTUwNzUxMjZaoA4wDDAKBgNVHRQEAwIBATANBgkqhkiG +9w0BAQsFAAOCAgEAZiUiWeXD7ei/G2T/nhgR/by9Tg58SEdqozAikzgOQtYmCF8v +3S3LDNOoOqMZrXlGndOjg6Cf+MqljWn9ZQ+2R0F1FJhv/0qKAurqoAqg95MjtmHB +MWVE0njStIM4YySrV2Ew0ihjYX0AQdV6PSBPjRRsbu5HcKUYmCp59Y34fUM6mfs4 +ha9HiTT5j/4R5Q6g3LxIc0KPq7Aw5o6F92D4iEVZwfMOWZHo5NbrEqvu92FX2WsT +g3/XlACGBtaegZA25aGPF5q87wP9QcU1LMnej1IQLMR0YSTA6l65iwjfXXeMP6c9 +B7DrRqmOYhMfz6Sekq8jv/mWaPk+3BmIoy5i3zLokIcbcyw6/GiJSK9KitYacOd4 +hDHZaPXSES99Op1dUKsJGySDCFgsJPaUuOVmmcW4UTAlxDCDhOtX1kxG1PTDeMyo +j2cLc5KUwa/yZ8YX9R1fSyobNP8i52WezlBAc47yC3IERmnmLWLeAxIRjKLCrjRJ +NSe6KxAWvTW1PuDO6vfDOSAaZFcDJ9i7Ew8WTwEIVKMjNagOa2E9RC/c9s5j0KwQ +iVBzOdSAwi/7EK26NDuFy49Ia3j/TNbQ7rEtT9lXd++8FBXB/cpASRldQZlm4loz +QHtA2a+snsI6GJrCaBwG4mS1m3Q78oWZLd7LWRZNUUwOBWA5CVG+A0UNp/s= +-----END X509 CRL----- diff --git a/tests/runtime/in_tcp.c b/tests/runtime/in_tcp.c index dc4eef1a975..a759f74d44b 100644 --- a/tests/runtime/in_tcp.c +++ b/tests/runtime/in_tcp.c @@ -37,6 +37,13 @@ #define TLS_CERTIFICATE_FILENAME FLB_TESTS_DATA_PATH "/data/tls/certificate.pem" #define TLS_PRIVATE_KEY_FILENAME FLB_TESTS_DATA_PATH "/data/tls/private_key.pem" +#define TLS_CA_FILE FLB_TESTS_DATA_PATH "/data/tls/ca_certificate.pem" +#define TLS_CLIENT_CERT_FILE FLB_TESTS_DATA_PATH "/data/tls/client_certificate.pem" +#define TLS_CLIENT_KEY_FILE FLB_TESTS_DATA_PATH "/data/tls/client_private_key.pem" +#define TLS_CLIENT_CERT_REVOKED_FILE FLB_TESTS_DATA_PATH "/data/tls/client_certificate_revoked.pem" +#define TLS_CLIENT_KEY_REVOKED_FILE FLB_TESTS_DATA_PATH "/data/tls/client_private_key_revoked.pem" +#define TLS_CRL_FILE FLB_TESTS_DATA_PATH "/data/tls/crl.pem" + struct test_ctx { flb_ctx_t *flb; /* Fluent Bit library context */ int i_ffd; /* Input fd */ @@ -547,6 +554,142 @@ void flb_test_tcp_with_tls() flb_free(ctx); } +/* + * The tcp input acts as a TLS server that verifies the client certificate + * against a CRL (tls.crl_file). A valid client must be accepted (records + * ingested); a revoked client must be rejected (no records). + */ +static void run_tls_crl_client(const char *client_cert, const char *client_key, + int expect_output) +{ + struct flb_connection *client_connection; + struct flb_upstream *upstream; + struct flb_lib_out_cb cb_data; + size_t sent; + struct test_ctx *ctx; + int ret; + int num; + struct flb_tls *tls; + + char *buf = "{\"test\":\"msg\"}"; + size_t size = strlen(buf); + + clear_output_num(); + + cb_data.cb = cb_check_result_json; + cb_data.data = "\"test\":\"msg\""; + + ctx = test_ctx_create(&cb_data); + if (!TEST_CHECK(ctx != NULL)) { + TEST_MSG("test_ctx_create failed"); + exit(EXIT_FAILURE); + } + + ret = flb_input_set(ctx->flb, ctx->i_ffd, + "tls", "on", + "tls.verify", "on", + "tls.vhost", TLS_CERTIFICATE_HOSTNAME, + "tls.crt_file", TLS_CERTIFICATE_FILENAME, + "tls.key_file", TLS_PRIVATE_KEY_FILENAME, + "tls.ca_file", TLS_CA_FILE, + "tls.crl_file", TLS_CRL_FILE, + NULL); + TEST_CHECK(ret == 0); + + ret = flb_output_set(ctx->flb, ctx->o_ffd, + "match", "*", + "format", "json", + NULL); + TEST_CHECK(ret == 0); + + /* Start the engine */ + ret = flb_start(ctx->flb); + TEST_CHECK(ret == 0); + + ret = flb_tls_init(); + TEST_CHECK(ret == 0); + + /* Client presents the certificate under test */ + tls = flb_tls_create(FLB_TLS_CLIENT_MODE, + FLB_FALSE, + FLB_TRUE, + TLS_CERTIFICATE_HOSTNAME, + NULL, + TLS_CA_FILE, + client_cert, + client_key, + NULL); + + TEST_CHECK(tls != NULL); + + /* + * Force TLS 1.2 so the client certificate is verified during the + * handshake. Under TLS 1.3 the client is authenticated after the + * handshake completes (post-handshake auth). + */ + ret = flb_tls_set_minmax_proto(tls, "TLSv1.2", "TLSv1.2"); + TEST_CHECK(ret == 0); + + upstream = flb_upstream_create(ctx->flb->config, + DEFAULT_HOST, + DEFAULT_PORT, + FLB_IO_TCP | FLB_IO_TLS, + tls); + + TEST_CHECK(upstream != NULL); + + flb_stream_disable_async_mode(&upstream->base); + + upstream->base.net.io_timeout = DEFAULT_IO_TIMEOUT; + + /* Connecting performs the TLS handshake (and client-cert verification) */ + client_connection = flb_upstream_conn_get(upstream); + + if (client_connection != NULL) { + ret = flb_io_net_write(client_connection, + (void *) buf, + size, + &sent); + (void) ret; + + /* waiting to flush */ + flb_time_msleep(1500); + } + + num = get_output_num(); + + if (expect_output) { + if (!TEST_CHECK(num > 0)) { + TEST_MSG("valid client: expected ingested records, got %d", num); + } + } + else { + if (!TEST_CHECK(num == 0)) { + TEST_MSG("revoked client: expected rejection, but %d records ingested", + num); + } + } + + sleep(1); + + flb_stop(ctx->flb); + flb_upstream_destroy(upstream); + flb_tls_destroy(tls); + flb_destroy(ctx->flb); + flb_free(ctx); +} + +void flb_test_tcp_tls_crl_valid_client() +{ + run_tls_crl_client(TLS_CLIENT_CERT_FILE, TLS_CLIENT_KEY_FILE, FLB_TRUE); +} + +void flb_test_tcp_tls_crl_revoked_client() +{ + run_tls_crl_client(TLS_CLIENT_CERT_REVOKED_FILE, TLS_CLIENT_KEY_REVOKED_FILE, + FLB_FALSE); +} + void flb_test_format_none() { struct flb_lib_out_cb cb_data; @@ -942,6 +1085,8 @@ TEST_LIST = { {"tcp", flb_test_tcp}, {"tcp_with_source_address", flb_test_tcp_with_source_address}, {"tcp_with_tls", flb_test_tcp_with_tls}, + {"tcp_with_tls_crl_valid_client", flb_test_tcp_tls_crl_valid_client}, + {"tcp_with_tls_crl_revoked_client", flb_test_tcp_tls_crl_revoked_client}, {"format_none", flb_test_format_none}, {"format_none_separator", flb_test_format_none_separator}, #ifdef FLB_HAVE_PARSER