diff --git a/.gitignore b/.gitignore index ba37a7bb55f..ef0e3aed015 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea .vscode +.vs .clang-format .DS_Store *~ @@ -41,3 +42,4 @@ workflow/ examples/wasi_serde_json/target/ # WASM test data tests/runtime/wasm/go/*.wasm +/out/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d9e7c879c9..9d3d4fc7e9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ option(FLB_WASM_STACK_PROTECT "Build with WASM runtime with strong stack protec option(FLB_ENFORCE_ALIGNMENT "Enable limited platform specific aligned memory access" No) option(FLB_KAFKA "Enable Kafka support" Yes) option(FLB_ZIG "Enable zig integration" Yes) +option(FLB_OPENSSL_STORE "Enable OpenSSL Store Support for TLS" No) # Native Metrics Support (cmetrics) option(FLB_METRICS "Enable metrics support" Yes) @@ -419,6 +420,15 @@ if (FLB_ZIG) endif() endif() +# Ensure OpenSSL Store support is available if TLS is enabled +if (FLB_OPENSSL_STORE) + if(NOT FLB_TLS) + message(FATAL_ERROR "FLB_ENABLE_OPENSSL_STORE requires FLB_TLS to be enabled.") + endif() + message(STATUS "OpenSSL Store defined") + add_definitions(-DFLB_USE_OPENSSL_STORE=1) +endif() + if(FLB_SMALL) if(CMAKE_COMPILER_IS_GNUCC) set(strip_flag " -s ") diff --git a/include/fluent-bit/flb_config.h b/include/fluent-bit/flb_config.h index b6090eea537..9972429bc74 100644 --- a/include/fluent-bit/flb_config.h +++ b/include/fluent-bit/flb_config.h @@ -101,6 +101,8 @@ struct flb_config { struct flb_cf *cf_opts; struct mk_list cf_parsers_list; + char* openssl_providers; + flb_sds_t program_name; /* argv[0] */ /* @@ -412,4 +414,8 @@ enum conf_type { #define FLB_CONF_STR_SCHED_CAP "scheduler.cap" #define FLB_CONF_STR_SCHED_BASE "scheduler.base" +/* OpenSSL Providers */ +#define FLB_CONF_STR_OPENSSL_PROVIDERS \ + "openssl.providers" + #endif diff --git a/include/fluent-bit/flb_input.h b/include/fluent-bit/flb_input.h index 1f8b076d5f7..253bdda4920 100644 --- a/include/fluent-bit/flb_input.h +++ b/include/fluent-bit/flb_input.h @@ -450,6 +450,7 @@ struct flb_input_instance { char *tls_min_version; /* Minimum protocol version of TLS */ char *tls_max_version; /* Maximum protocol version of TLS */ char *tls_ciphers; /* TLS ciphers */ + char *tls_provider_query; /* OpenSSL Provider Query */ struct mk_list *tls_config_map; diff --git a/include/fluent-bit/flb_output.h b/include/fluent-bit/flb_output.h index 848d8bde538..19aa5937ad7 100644 --- a/include/fluent-bit/flb_output.h +++ b/include/fluent-bit/flb_output.h @@ -369,6 +369,8 @@ struct flb_output_instance { char *tls_min_version; /* Minimum protocol version of TLS */ char *tls_max_version; /* Maximum protocol version of TLS */ char *tls_ciphers; /* TLS ciphers */ + char *tls_provider_query; /* OpenSSL Provider Query */ + # if defined(FLB_SYSTEM_WINDOWS) char *tls_win_certstore_name; /* CertStore Name (Windows) */ int tls_win_use_enterprise_certstore; /* Use enterprise CertStore */ diff --git a/include/fluent-bit/flb_upstream_node.h b/include/fluent-bit/flb_upstream_node.h index 8f203392f28..2efa821fcc0 100644 --- a/include/fluent-bit/flb_upstream_node.h +++ b/include/fluent-bit/flb_upstream_node.h @@ -43,6 +43,7 @@ struct flb_upstream_node { char *tls_crt_file; /* Certificate */ char *tls_key_file; /* Cert Key */ char *tls_key_passwd; /* Cert Key Password */ + char *tls_provider_query; /* OpenSSL Provider Query */ /* context with mbedTLS contexts and data */ struct flb_tls *tls; @@ -74,6 +75,7 @@ struct flb_upstream_node *flb_upstream_node_create(flb_sds_t name, flb_sds_t hos const char *tls_crt_file, const char *tls_key_file, const char *tls_key_passwd, + const char *tls_provider_query, struct flb_hash_table *ht, struct flb_config *config); const char *flb_upstream_node_get_property(const char *prop, diff --git a/include/fluent-bit/tls/flb_tls.h b/include/fluent-bit/tls/flb_tls.h index c7165538e95..c432c311cd0 100644 --- a/include/fluent-bit/tls/flb_tls.h +++ b/include/fluent-bit/tls/flb_tls.h @@ -69,7 +69,8 @@ struct flb_tls_backend { void *(*context_create) (int, int, int, const char *, const char *, const char *, const char *, - const char *, const char *); + const char *, const char *, + const char *); /* destroy backend context */ void (*context_destroy) (void *); @@ -118,13 +119,17 @@ struct flb_tls { int flb_tls_init(); +void flb_tls_configure(struct flb_config* config); +void flb_tls_cleanup(void); + struct flb_tls *flb_tls_create(int mode, int verify, int debug, const char *vhost, const char *ca_path, const char *ca_file, const char *crt_file, - const char *key_file, const char *key_passwd); + const char *key_file, const char *key_passwd, + const char *additional_data); int flb_tls_destroy(struct flb_tls *tls); diff --git a/plugins/filter_kubernetes/kube_meta.c b/plugins/filter_kubernetes/kube_meta.c index 83ba20167e3..410b7441043 100644 --- a/plugins/filter_kubernetes/kube_meta.c +++ b/plugins/filter_kubernetes/kube_meta.c @@ -1741,7 +1741,7 @@ static int flb_kubelet_network_init(struct flb_kube *ctx, struct flb_config *con ctx->tls_vhost, ctx->tls_ca_path, ctx->tls_ca_file, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (!ctx->kubelet_tls) { return -1; } @@ -1794,7 +1794,7 @@ static int flb_kube_network_init(struct flb_kube *ctx, struct flb_config *config ctx->tls_vhost, ctx->tls_ca_path, ctx->tls_ca_file, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (!ctx->tls) { return -1; } diff --git a/plugins/filter_nightfall/nightfall.c b/plugins/filter_nightfall/nightfall.c index 3e37d2a0bc4..7aa375be41e 100644 --- a/plugins/filter_nightfall/nightfall.c +++ b/plugins/filter_nightfall/nightfall.c @@ -97,7 +97,7 @@ static int cb_nightfall_init(struct flb_filter_instance *f_ins, ctx->tls_vhost, ctx->tls_ca_path, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (!ctx->tls) { flb_plg_error(f_ins, "tls initialization error"); flb_free(ctx); diff --git a/plugins/in_kubernetes_events/kubernetes_events_conf.c b/plugins/in_kubernetes_events/kubernetes_events_conf.c index e40d67b415e..d367aa63eec 100644 --- a/plugins/in_kubernetes_events/kubernetes_events_conf.c +++ b/plugins/in_kubernetes_events/kubernetes_events_conf.c @@ -109,7 +109,7 @@ static int network_init(struct k8s_events *ctx, struct flb_config *config) ctx->tls_vhost, ctx->tls_ca_path, ctx->tls_ca_file, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (!ctx->tls) { return -1; } diff --git a/plugins/out_azure_blob/azure_blob_conf.c b/plugins/out_azure_blob/azure_blob_conf.c index ea883a01852..cae7654ad07 100644 --- a/plugins/out_azure_blob/azure_blob_conf.c +++ b/plugins/out_azure_blob/azure_blob_conf.c @@ -375,6 +375,7 @@ static int flb_azure_blob_apply_remote_configuration(struct flb_azure_blob *cont NULL, NULL, NULL, + NULL, NULL); if (tls_context == NULL) { diff --git a/plugins/out_azure_kusto/azure_kusto_conf.c b/plugins/out_azure_kusto/azure_kusto_conf.c index de09726052e..522d4eda186 100644 --- a/plugins/out_azure_kusto/azure_kusto_conf.c +++ b/plugins/out_azure_kusto/azure_kusto_conf.c @@ -89,7 +89,7 @@ static struct flb_upstream_node *flb_upstream_node_create_url(struct flb_azure_k NULL, sds_host, sds_port, FLB_TRUE, ctx->ins->tls->verify, ctx->ins->tls->verify_hostname, ctx->ins->tls->debug, ctx->ins->tls->vhost, NULL, NULL, NULL, - NULL, NULL, kv, config); + NULL, NULL, NULL, kv, config); if (!node) { flb_plg_error(ctx->ins, "error creating resource upstream node"); diff --git a/plugins/out_bigquery/bigquery.c b/plugins/out_bigquery/bigquery.c index b21cff5241c..027a5e76c90 100644 --- a/plugins/out_bigquery/bigquery.c +++ b/plugins/out_bigquery/bigquery.c @@ -695,7 +695,8 @@ static int cb_bigquery_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_tls) { flb_plg_error(ctx->ins, "Failed to create TLS context"); @@ -734,7 +735,8 @@ static int cb_bigquery_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_sts_tls) { flb_plg_error(ctx->ins, "Failed to create TLS context"); @@ -765,7 +767,8 @@ static int cb_bigquery_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->google_sts_tls) { flb_plg_error(ctx->ins, "Failed to create TLS context"); @@ -793,7 +796,8 @@ static int cb_bigquery_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->google_iam_tls) { flb_plg_error(ctx->ins, "Failed to create TLS context"); diff --git a/plugins/out_cloudwatch_logs/cloudwatch_logs.c b/plugins/out_cloudwatch_logs/cloudwatch_logs.c index c5e808ae141..e2b09a240ac 100644 --- a/plugins/out_cloudwatch_logs/cloudwatch_logs.c +++ b/plugins/out_cloudwatch_logs/cloudwatch_logs.c @@ -251,7 +251,8 @@ static int cb_cloudwatch_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->cred_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); @@ -266,7 +267,8 @@ static int cb_cloudwatch_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->client_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); goto error; @@ -302,7 +304,8 @@ static int cb_cloudwatch_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->sts_tls) { flb_errno(); goto error; diff --git a/plugins/out_es/es_conf.c b/plugins/out_es/es_conf.c index 4bc2977c5eb..0364e5387d6 100644 --- a/plugins/out_es/es_conf.c +++ b/plugins/out_es/es_conf.c @@ -382,7 +382,8 @@ struct flb_elasticsearch *flb_es_conf_create(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_tls) { flb_errno(); flb_es_conf_destroy(ctx); @@ -443,7 +444,8 @@ struct flb_elasticsearch *flb_es_conf_create(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_sts_tls) { flb_errno(); flb_es_conf_destroy(ctx); diff --git a/plugins/out_kinesis_firehose/firehose.c b/plugins/out_kinesis_firehose/firehose.c index d91c6f00a8a..f998f73a9cb 100644 --- a/plugins/out_kinesis_firehose/firehose.c +++ b/plugins/out_kinesis_firehose/firehose.c @@ -157,7 +157,8 @@ static int cb_firehose_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->cred_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); @@ -172,7 +173,8 @@ static int cb_firehose_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->client_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); goto error; @@ -208,7 +210,8 @@ static int cb_firehose_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->sts_tls) { flb_errno(); goto error; diff --git a/plugins/out_kinesis_streams/kinesis.c b/plugins/out_kinesis_streams/kinesis.c index a225f6007f7..d90a02e4394 100644 --- a/plugins/out_kinesis_streams/kinesis.c +++ b/plugins/out_kinesis_streams/kinesis.c @@ -169,7 +169,8 @@ static int cb_kinesis_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->cred_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); @@ -184,7 +185,8 @@ static int cb_kinesis_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->client_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); goto error; @@ -227,7 +229,8 @@ static int cb_kinesis_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->sts_tls) { flb_errno(); goto error; diff --git a/plugins/out_opensearch/os_conf.c b/plugins/out_opensearch/os_conf.c index a42cedbd31d..9c0ec9e42e3 100644 --- a/plugins/out_opensearch/os_conf.c +++ b/plugins/out_opensearch/os_conf.c @@ -257,7 +257,8 @@ struct flb_opensearch *flb_os_conf_create(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_tls) { flb_errno(); flb_os_conf_destroy(ctx); @@ -318,7 +319,8 @@ struct flb_opensearch *flb_os_conf_create(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->aws_sts_tls) { flb_errno(); flb_os_conf_destroy(ctx); diff --git a/plugins/out_s3/s3.c b/plugins/out_s3/s3.c index 3b1edafbdab..f5e50bc19af 100644 --- a/plugins/out_s3/s3.c +++ b/plugins/out_s3/s3.c @@ -785,7 +785,8 @@ static int cb_s3_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->client_tls) { flb_plg_error(ctx->ins, "Failed to create tls context"); return -1; @@ -801,7 +802,8 @@ static int cb_s3_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->provider_tls) { flb_errno(); return -1; @@ -835,7 +837,8 @@ static int cb_s3_init(struct flb_output_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ctx->sts_provider_tls) { flb_errno(); diff --git a/src/aws/flb_aws_credentials.c b/src/aws/flb_aws_credentials.c index 75f13b111f2..1a4f062902e 100644 --- a/src/aws/flb_aws_credentials.c +++ b/src/aws/flb_aws_credentials.c @@ -383,7 +383,8 @@ struct flb_aws_provider *flb_managed_chain_provider_create(struct flb_output_ins ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!cred_tls) { flb_plg_error(ins, "Failed to create TLS instance for AWS Provider"); flb_errno(); @@ -434,7 +435,8 @@ struct flb_aws_provider *flb_managed_chain_provider_create(struct flb_output_ins ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!sts_tls) { flb_plg_error(ins, "Failed to create TLS instance for AWS STS Credential " "Provider"); diff --git a/src/flb_config.c b/src/flb_config.c index 407464b4942..ea565c51248 100644 --- a/src/flb_config.c +++ b/src/flb_config.c @@ -205,6 +205,11 @@ struct flb_service_config service_configs[] = { FLB_CONF_TYPE_BOOL, offsetof(struct flb_config, ensure_thread_safety_on_hot_reloading)}, + /* OpenSSL Providers */ + { FLB_CONF_STR_OPENSSL_PROVIDERS, + FLB_CONF_TYPE_STR, + offsetof(struct flb_config, openssl_providers) }, + {NULL, FLB_CONF_TYPE_OTHER, 0} /* end of array */ }; @@ -308,6 +313,8 @@ struct flb_config *flb_config_init() config->shutdown_by_hot_reloading = FLB_FALSE; config->hot_reloading = FLB_FALSE; + config->openssl_providers = NULL; + #ifdef FLB_SYSTEM_WINDOWS config->win_maxstdio = 512; #endif @@ -569,6 +576,10 @@ void flb_config_exit(struct flb_config *config) flb_cf_destroy(config->cf_main); } + if (config->openssl_providers) { + flb_free(config->openssl_providers); + } + /* cf_opts' lifetime should differ from config's lifetime. * This member should be storing just for the cf_opts reference. * Don't destroy it here. diff --git a/src/flb_input.c b/src/flb_input.c index 2ee8aa9f048..5274b5a0f94 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -405,6 +405,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_provider_query = NULL; #endif /* Plugin requires a co-routine context ? */ @@ -686,6 +687,9 @@ int flb_input_set_property(struct flb_input_instance *ins, else if (prop_key_check("tls.ciphers", k, len) == 0) { flb_utils_set_plugin_string_property("tls.ciphers", &ins->tls_ciphers, tmp); } + else if (prop_key_check("tls.provider_query", k, len) == 0) { + flb_utils_set_plugin_string_property("tls.provider_query", &ins->tls_provider_query, tmp); + } #endif else if (prop_key_check("storage.type", k, len) == 0 && tmp) { /* Set the storage type */ @@ -869,6 +873,10 @@ void flb_input_instance_destroy(struct flb_input_instance *ins) flb_sds_destroy(ins->tls_ciphers); } + if (ins->tls_provider_query) { + flb_sds_destroy(ins->tls_provider_query); + } + /* release the tag if any */ flb_sds_destroy(ins->tag); @@ -1285,7 +1293,8 @@ int flb_input_instance_init(struct flb_input_instance *ins, ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (ins->tls == NULL) { flb_error("[input %s] error initializing TLS context", diff --git a/src/flb_lib.c b/src/flb_lib.c index 30d4d99dd40..c72a18dd4aa 100644 --- a/src/flb_lib.c +++ b/src/flb_lib.c @@ -120,7 +120,7 @@ static inline struct flb_filter_instance *filter_instance_get(flb_ctx_t *ctx, return NULL; } -void flb_init_env() +void flb_init_env(void) { flb_tls_init(); flb_coro_init(); @@ -135,6 +135,11 @@ void flb_init_env() cmt_initialize(); } +void flb_configure_env(struct flb_config* config) +{ + flb_tls_configure(config); +} + flb_ctx_t *flb_create() { int ret; @@ -864,6 +869,8 @@ int static do_start(flb_ctx_t *ctx) flb_debug("[lib] context set: %p", ctx); + flb_configure_env(ctx->config); + /* set context as the last active one */ /* spawn worker thread */ @@ -981,6 +988,8 @@ int flb_stop(flb_ctx_t *ctx) } flb_debug("[lib] Fluent Bit engine stopped"); + flb_tls_cleanup(); + return ret; } diff --git a/src/flb_oauth2.c b/src/flb_oauth2.c index 866fbe8e132..eb7c3d6b1bb 100644 --- a/src/flb_oauth2.c +++ b/src/flb_oauth2.c @@ -220,7 +220,8 @@ struct flb_oauth2 *flb_oauth2_create(struct flb_config *config, NULL, /* ca_file */ NULL, /* crt_file */ NULL, /* key_file */ - NULL); /* key_passwd */ + NULL, /* key_passwd */ + NULL); /* openssl_provider */ if (!ctx->tls) { flb_error("[oauth2] error initializing TLS context"); goto error; diff --git a/src/flb_output.c b/src/flb_output.c index a98960f0bbb..3f18cdcd559 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -184,6 +184,9 @@ static void flb_output_free_properties(struct flb_output_instance *ins) if (ins->tls_ciphers) { flb_sds_destroy(ins->tls_ciphers); } + if (ins->tls_provider_query) { + flb_sds_destroy(ins->tls_provider_query); + } # if defined(FLB_SYSTEM_WINDOWS) if (ins->tls_win_certstore_name) { flb_sds_destroy(ins->tls_win_certstore_name); @@ -766,6 +769,8 @@ 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_provider_query = NULL; + # if defined(FLB_SYSTEM_WINDOWS) instance->tls_win_certstore_name = NULL; instance->tls_win_use_enterprise_certstore = FLB_FALSE; @@ -994,6 +999,9 @@ int flb_output_set_property(struct flb_output_instance *ins, else if (prop_key_check("tls.ciphers", k, len) == 0) { flb_utils_set_plugin_string_property("tls.ciphers", &ins->tls_ciphers, tmp); } + else if (prop_key_check("tls.provider_query", k, len) == 0) { + flb_utils_set_plugin_string_property("tls.provider_query", &ins->tls_provider_query, tmp); + } # if defined(FLB_SYSTEM_WINDOWS) else if (prop_key_check("tls.windows.certstore_name", k, len) == 0 && tmp) { flb_utils_set_plugin_string_property("tls.windows.certstore_name", &ins->tls_win_certstore_name, tmp); @@ -1350,7 +1358,8 @@ int flb_output_init_all(struct flb_config *config) ins->tls_ca_file, ins->tls_crt_file, ins->tls_key_file, - ins->tls_key_passwd); + ins->tls_key_passwd, + ins->tls_provider_query); if (!ins->tls) { flb_error("[output %s] error initializing TLS context", ins->name); diff --git a/src/flb_upstream_ha.c b/src/flb_upstream_ha.c index d01e55ad5f3..418d7f906ff 100644 --- a/src/flb_upstream_ha.c +++ b/src/flb_upstream_ha.c @@ -153,6 +153,7 @@ static struct flb_upstream_node *create_node(int id, char *tls_crt_file = NULL; char *tls_key_file = NULL; char *tls_key_passwd = NULL; + char *tls_provider_query = NULL; flb_sds_t translated_value; struct cfl_list *head; struct cfl_kvpair *entry; @@ -161,7 +162,7 @@ static struct flb_upstream_node *create_node(int id, "tls", "tls.vhost", "tls.verify", "tls.debug", "tls.ca_path", "tls.ca_file", "tls.crt_file", "tls.key_file", "tls.key_passwd", - "tls.verify_hostname", NULL}; + "tls.verify_hostname", "tls.provider_query", NULL}; struct flb_upstream_node *node; @@ -235,6 +236,8 @@ static struct flb_upstream_node *create_node(int id, /* tls.key_file */ tls_key_passwd = flb_cf_section_property_get_string(cf, s, "tls.key_passwd"); + tls_provider_query = flb_cf_section_property_get_string(cf, s, "tls.provider_query"); + translate_environment_variables((flb_sds_t *) &name, config, FLB_TRUE); translate_environment_variables((flb_sds_t *) &host, config, FLB_TRUE); translate_environment_variables((flb_sds_t *) &port, config, FLB_TRUE); @@ -244,6 +247,7 @@ static struct flb_upstream_node *create_node(int id, translate_environment_variables((flb_sds_t *) &tls_crt_file, config, FLB_TRUE); translate_environment_variables((flb_sds_t *) &tls_key_file, config, FLB_TRUE); translate_environment_variables((flb_sds_t *) &tls_key_passwd, config, FLB_TRUE); + translate_environment_variables((flb_sds_t *) &tls_provider_query, config, FLB_TRUE); /* * Create hash table to store unknown key/values that might be used @@ -322,7 +326,7 @@ static struct flb_upstream_node *create_node(int id, tls_verify_hostname, tls_debug, tls_vhost, tls_ca_path, tls_ca_file, tls_crt_file, tls_key_file, - tls_key_passwd, ht, config); + tls_key_passwd, tls_provider_query, ht, config); /* Teardown for created flb_sds_t stuffs by flb_cf_section_property_get_string(). */ if (tls_vhost != NULL) { @@ -349,6 +353,10 @@ static struct flb_upstream_node *create_node(int id, flb_sds_destroy(tls_key_passwd); } + if (tls_provider_query != NULL) { + flb_sds_destroy(tls_provider_query); + } + return node; } diff --git a/src/flb_upstream_node.c b/src/flb_upstream_node.c index 5131efd0d6b..47e4b742f4f 100644 --- a/src/flb_upstream_node.c +++ b/src/flb_upstream_node.c @@ -38,6 +38,7 @@ struct flb_upstream_node *flb_upstream_node_create(flb_sds_t name, flb_sds_t hos const char *tls_crt_file, const char *tls_key_file, const char *tls_key_passwd, + const char* tls_provider_query, struct flb_hash_table *ht, struct flb_config *config) { @@ -121,6 +122,12 @@ struct flb_upstream_node *flb_upstream_node_create(flb_sds_t name, flb_sds_t hos flb_upstream_node_destroy(node); return NULL; } + + node->tls_provider_query = flb_sds_create(tls_provider_query); + if (!node->tls_provider_query) { + flb_upstream_node_destroy(node); + return NULL; + } #endif /* hash table */ @@ -137,7 +144,8 @@ struct flb_upstream_node *flb_upstream_node_create(flb_sds_t name, flb_sds_t hos tls_ca_file, tls_crt_file, tls_key_file, - tls_key_passwd); + tls_key_passwd, + tls_provider_query); if (!node->tls) { flb_error("[upstream_node] error initializing TLS context " "on node '%s'", name); @@ -215,6 +223,7 @@ void flb_upstream_node_destroy(struct flb_upstream_node *node) flb_sds_destroy(node->tls_crt_file); flb_sds_destroy(node->tls_key_file); flb_sds_destroy(node->tls_key_passwd); + flb_sds_destroy(node->tls_provider_query); if (node->tls) { flb_tls_destroy(node->tls); } diff --git a/src/tls/flb_tls.c b/src/tls/flb_tls.c index f0e42c265cf..d537e555c32 100644 --- a/src/tls/flb_tls.c +++ b/src/tls/flb_tls.c @@ -98,6 +98,12 @@ struct flb_config_map tls_configmap[] = { "Specify TLS ciphers up to TLSv1.2" }, + { + FLB_CONFIG_MAP_STR, "tls.provider_query", NULL, + 0, FLB_FALSE, 0, + "OpenSSL Provider Query to use for TLS operations" + }, + /* EOF */ {0} }; @@ -188,7 +194,8 @@ struct flb_tls *flb_tls_create(int mode, const char *ca_file, const char *crt_file, const char *key_file, - const char *key_passwd) + const char *key_passwd, + const char *additional_data) { void *backend; struct flb_tls *tls; @@ -199,7 +206,8 @@ struct flb_tls *flb_tls_create(int mode, backend = tls_context_create(verify, debug, mode, vhost, ca_path, ca_file, - crt_file, key_file, key_passwd); + crt_file, key_file, key_passwd, + additional_data); if (!backend) { flb_error("[tls] could not create TLS backend"); return NULL; @@ -255,6 +263,14 @@ int flb_tls_init() return tls_init(); } +void flb_tls_configure(struct flb_config* config) +{ + if (!config) { + return; + } + tls_configure(config); +} + int flb_tls_destroy(struct flb_tls *tls) { if (tls->ctx) { @@ -276,6 +292,11 @@ int flb_tls_destroy(struct flb_tls *tls) return 0; } +void flb_tls_cleanup(void) +{ + tls_cleanup(); +} + int flb_tls_set_alpn(struct flb_tls *tls, const char *alpn) { if (tls->ctx) { diff --git a/src/tls/openssl.c b/src/tls/openssl.c index 1d95293498f..32287f2e660 100644 --- a/src/tls/openssl.c +++ b/src/tls/openssl.c @@ -17,8 +17,21 @@ * limitations under the License. */ + /* + * OPENSSL_VERSION_NUMBER has the following semantics + * + * 0x010100000L M = major F = fix S = status + * MMNNFFPPS N = minor P = patch + */ +#define OPENSSL_1_1_0 0x010100000L +#define OPENSSL_3_0 0x030000000L + #include #include +#ifdef FLB_USE_OPENSSL_STORE +#include +#include +#endif #include #include @@ -29,6 +42,12 @@ #include #include #include +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 +#include +#ifdef FLB_USE_OPENSSL_STORE +#include +#endif +#endif #include #ifdef FLB_SYSTEM_MACOS @@ -42,13 +61,14 @@ strtok_s(str, delimiter, context) #endif -/* - * OPENSSL_VERSION_NUMBER has the following semantics - * - * 0x010100000L M = major F = fix S = status - * MMNNFFPPS N = minor P = patch - */ -#define OPENSSL_1_1_0 0x010100000L + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 +#define MAX_OPENSSL_PROVIDERS 4 +struct openssl_provider_support { + int current_provider; + OSSL_PROVIDER* provider[MAX_OPENSSL_PROVIDERS]; +}; +#endif /* OpenSSL library context */ struct tls_context { @@ -61,6 +81,10 @@ struct tls_context { int use_enterprise_store; #endif pthread_mutex_t mutex; +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + X509 *store_cert; + EVP_PKEY *store_pkey; +#endif }; struct tls_session { @@ -71,8 +95,95 @@ struct tls_session { struct tls_context *parent; /* parent struct tls_context ref */ }; + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 + +/* List of providers to load and activate for OpenSSL */ +static struct openssl_provider_support openssl_providers; + + +static void openssl_providers_reset(void) +{ + flb_idebug("[tls] resetting providers"); + for (int i = 0; i < MAX_OPENSSL_PROVIDERS; i++) + if (openssl_providers.provider[i]) { + OSSL_PROVIDER_unload(openssl_providers.provider[i]); + openssl_providers.provider[i] = NULL; + } + openssl_providers.current_provider = 0; +} + +static bool openssl_provider_loaded(const char* provider) +{ + const char* name = NULL; + + if (!provider) { + return false; + } + for (int i = 0; i < MAX_OPENSSL_PROVIDERS; i++) { + if (openssl_providers.provider[i]) { + name = OSSL_PROVIDER_get0_name(openssl_providers.provider[i]); + if (name && strcmp(name, provider) == 0) { + return true; + } + } + } + return false; +} + +bool openssl_providers_loaded(const char* providers) +{ + const char* delim = ";"; + char* provider_list = NULL; + char* provider = NULL; + bool all_providers_loaded = true; + + if (!providers) { + return true; + } + + provider_list = flb_strdup(providers); + provider = strtok(provider_list, delim); + while (provider && all_providers_loaded) { + all_providers_loaded = openssl_provider_loaded(provider); + provider = strtok(NULL, delim); + } + + flb_free(provider_list); + return all_providers_loaded; +} + +static void openssl_load_provider(const char* provider) +{ + if(!provider) { + return; + } + + flb_idebug("[tls] loading provider '%s'", provider); + if (openssl_provider_loaded(provider)) { + flb_idebug("[tls] - provider already loaded"); + return; + } + + if (openssl_providers.current_provider >= MAX_OPENSSL_PROVIDERS) { + flb_error("[tls] - too many providers loaded"); + return; + } + + openssl_providers.provider[openssl_providers.current_provider] = OSSL_PROVIDER_load(NULL, provider); + if (!openssl_providers.provider[openssl_providers.current_provider]) { + flb_error("[tls] failed to load provider - %s", ERR_error_string(ERR_get_error(), NULL)); + return; + } + openssl_providers.current_provider++; + return; +} + +#endif + static int tls_init(void) { + flb_idebug("[tls] init"); /* * Explicit initialization is needed for older versions of * OpenSSL (before v1.1.0). @@ -84,10 +195,56 @@ static int tls_init(void) SSL_load_error_strings(); SSL_library_init(); #endif + + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 + /* Initialise the Providers Struct */ + openssl_providers.current_provider = 0; + for (int i = 0; i < MAX_OPENSSL_PROVIDERS; i++) { + openssl_providers.provider[i] = NULL; + } +#endif return 0; } +static void tls_configure(struct flb_config* config) +{ +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 + + int ret; + const char* delim = ";"; + char* provider_list; + const char* provider; + + if (!config) { + return; + } + + openssl_providers_reset(); /* Could be a reconfig - start from scratch */ + + if (!config->openssl_providers) { + return; + } + /* Load configured OpenSSL providers */ + provider_list = flb_strdup(config->openssl_providers); + provider = strtok(provider_list, delim); + while (provider) { + openssl_load_provider(provider); + provider = strtok(NULL, delim); + } + flb_free(provider_list); + +#endif +} + +static void tls_cleanup(void) +{ +#if OPENSSL_VERSION_NUMBER >= OPENSSL_3_0 + openssl_providers_reset(); +#endif +} + static void tls_info_callback(const SSL *s, int where, int ret) { int w; @@ -146,9 +303,19 @@ static void tls_context_destroy(void *ctx_backend) SSL_CTX_free(ctx->ctx); +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + if (ctx->store_cert != NULL) { + X509_free(ctx->store_cert); + ctx->store_cert = NULL; + } + if (ctx->store_pkey != NULL) { + EVP_PKEY_free(ctx->store_pkey); + ctx->store_pkey = NULL; + } +#endif + if (ctx->alpn != NULL) { flb_free(ctx->alpn); - ctx->alpn = NULL; } @@ -536,6 +703,149 @@ static void ssl_key_logger(const SSL *ssl, const char *line) } #endif +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + +/* Checks if the given path *could* be a URI, i.e it starts with something ending in a : + that matches the RFC 3986 definition */ +static bool could_be_uri(const char* path) +{ + const char* colon = NULL; + unsigned char ch; + + /* If the path is empty or doesn't start with a character */ + if (!path || + !isalpha((unsigned char)path[0])) { + return false; + } + + /* Check for a colon in the path */ + colon = strchr(path, ':'); + if (!colon || colon == path) { + return false; + } + + /* Check that the scheme is RFC 3986 compliant-ish */ + for (const char* current = path; current < colon; ++current) { + ch = (unsigned char)*current; + if (!isalnum(ch) && ch != '+' && ch != '-' && ch != '.') { + return false; + } + } + + return true; /* Could be a URI */ +} + +/* This function will return true if the item requested was read (or attempted to be + read) from the given store, or false if it is not. A false indicates the item was + most likely *not* a valid store item from the requested store. + + *arg will be set to the item if successfully decoded, or NULL otherwise. A NULL + indicates a problem in retrieving the item in the correct form from the store. */ +static bool openssl_provider_get_item(void** arg, const char *store_uri, + const char* provider_query, + bool (*get_item)(OSSL_STORE_INFO*, void**)) +{ + bool gotItem = false; + OSSL_STORE_CTX* store = NULL; + OSSL_STORE_INFO* info = NULL; + + if (!arg || !store_uri || !provider_query || !get_item || + !could_be_uri(store_uri)) { + flb_debug("[tls] Invalid arguments provided to openssl_provider_get_item"); + return false; + } + + flb_debug("[tls] Loading store item; query: %s, uri: %s, arg: %p", + provider_query, store_uri, *arg); + store = OSSL_STORE_open_ex(store_uri, NULL, provider_query, + NULL, NULL, NULL, NULL, NULL); + if (!store) { + flb_debug("[tls] Failed to load store %s", store_uri); + return false; + } + + info = OSSL_STORE_load(store); + if(!info) { + flb_debug("[tls] Failed to retrieve store info %s", store_uri); + OSSL_STORE_close(store); + return false; + } + + gotItem = get_item(info, arg); + + OSSL_STORE_INFO_free(info); + OSSL_STORE_close(store); + + return gotItem; +} + +/* This function will return true if the cert requested was read (or attempted to be + read) from the given store, or false if it is not. + + *arg will be set to the certificate if successfully decoded, or NULL otherwise. */ +static bool openssl_provider_get_certificate(OSSL_STORE_INFO* store_info, void** arg) +{ + X509** cert = NULL; + const unsigned char* p = NULL; + unsigned char* buf = NULL; + int item_type = 0; + int len = 0; + + if (!store_info || !arg) { + return false; + } + cert = (X509**)arg; + + item_type = OSSL_STORE_INFO_get_type(store_info); + if (item_type != OSSL_STORE_INFO_CERT) { + flb_debug("[tls] Store Item is not a Certificate %d", item_type); + return false; + } + + /* Serialise and De - Serialise to remove the provider query. Seems to interfere with + the signature later on */ + len = i2d_X509(OSSL_STORE_INFO_get0_CERT(store_info), &buf); + if (len < 0) { + flb_error("[tls] Couldn't serialise to DER %d", item_type); + return false; + } + p = buf; + + *cert = d2i_X509(NULL, &p, len); + OPENSSL_free(buf); + + return true; +} + +/* This function will return true if the key pointer requested was read (or attempted to + be read) from the given store, or false if it is not. + + *arg will be set to the key pointer if successfully decoded, or NULL otherwise. */ +static bool openssl_provider_get_private_key(OSSL_STORE_INFO* store_info, void** arg) +{ + EVP_PKEY** key = NULL; + int item_type = 0; + + if (!store_info || !arg) { + return false; + } + + key = (EVP_PKEY**)arg; + + item_type = OSSL_STORE_INFO_get_type(store_info); + if (item_type != OSSL_STORE_INFO_PKEY) + { + flb_debug("[tls] Store Item is not a Private Key %d", item_type); + return false; + } + + *key = OSSL_STORE_INFO_get1_PKEY(store_info); + + return true; +} + +#endif + static void *tls_context_create(int verify, int debug, int mode, @@ -544,7 +854,8 @@ static void *tls_context_create(int verify, const char *ca_file, const char *crt_file, const char *key_file, - const char *key_passwd) + const char *key_passwd, + const char *provider_query) { int ret; SSL_CTX *ssl_ctx; @@ -607,6 +918,10 @@ static void *tls_context_create(int verify, ctx->mode = mode; ctx->alpn = NULL; ctx->debug_level = debug; +#ifdef FLB_USE_OPENSSL_STORE + ctx->store_cert = NULL; + ctx->store_pkey = NULL; +#endif pthread_mutex_init(&ctx->mutex, NULL); /* Verify peer: by default OpenSSL always verify peer */ @@ -642,28 +957,68 @@ static void *tls_context_create(int verify, /* crt_file */ if (crt_file) { - ret = SSL_CTX_use_certificate_chain_file(ssl_ctx, crt_file); - if (ret != 1) { - ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)-1); - flb_error("[tls] crt_file '%s' %lu: %s", - crt_file, ERR_get_error(), err_buf); - goto error; +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + /* Try and open this as a store item first */ + if (openssl_provider_get_item((void**)&ctx->store_cert, crt_file, + provider_query, openssl_provider_get_certificate)) { + ret = SSL_CTX_use_certificate(ctx->ctx, ctx->store_cert); + if (ret != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] crt_store '%s' %lu: %s", + crt_file, ERR_get_error(), err_buf); + goto error; + } } + else { + /* Fall back to handling this as a file*/ + ctx->store_cert = NULL; +#endif + ret = SSL_CTX_use_certificate_chain_file(ssl_ctx, crt_file); + if (ret != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] crt_file '%s' %lu: %s", + crt_file, ERR_get_error(), err_buf); + goto error; + } + +#ifdef FLB_USE_OPENSSL_STORE + } +#endif } /* key_file */ if (key_file) { if (key_passwd) { SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, - (void *) key_passwd); + (void*)key_passwd); } - ret = SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, - SSL_FILETYPE_PEM); - if (ret != 1) { - ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)-1); - flb_error("[tls] key_file '%s' %lu: %s", - crt_file, ERR_get_error(), err_buf); +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + /* Try and open this as a store item if we had no key password */ + else if (openssl_provider_get_item((void**)&ctx->store_pkey, key_file, + provider_query, openssl_provider_get_private_key)) { + ret = SSL_CTX_use_PrivateKey(ctx->ctx, ctx->store_pkey); + + if (ret != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] key_store '%s' %lu: %s", + key_file, ERR_get_error(), err_buf); + goto error; + } } + else { + ctx->store_pkey = NULL; + +#endif + ret = SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, + SSL_FILETYPE_PEM); + if (ret != 1) { + ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf) - 1); + flb_error("[tls] key_file '%s' %lu: %s", + key_file, ERR_get_error(), err_buf); + } +#if defined(FLB_USE_OPENSSL_STORE) && (OPENSSL_VERSION_NUMBER >= OPENSSL_3_0) + } +#endif /* Make sure the key and certificate file match */ if (SSL_CTX_check_private_key(ssl_ctx) != 1) { diff --git a/tests/runtime/in_tcp.c b/tests/runtime/in_tcp.c index 732af004198..e80ef98cc84 100644 --- a/tests/runtime/in_tcp.c +++ b/tests/runtime/in_tcp.c @@ -373,6 +373,7 @@ void flb_test_tcp_with_tls() NULL, NULL, NULL, + NULL, NULL); TEST_CHECK(tls != NULL); diff --git a/tests/runtime/out_tcp.c b/tests/runtime/out_tcp.c index 98f323ba3ed..99b9e21cffa 100644 --- a/tests/runtime/out_tcp.c +++ b/tests/runtime/out_tcp.c @@ -330,6 +330,7 @@ void flb_test_tcp_with_tls() NULL, TLS_CERTIFICATE_FILENAME, TLS_PRIVATE_KEY_FILENAME, + NULL, NULL); TEST_CHECK(tls != NULL);