diff options
Diffstat (limited to 'fluent-bit/src/aws/flb_aws_credentials.c')
-rw-r--r-- | fluent-bit/src/aws/flb_aws_credentials.c | 862 |
1 files changed, 862 insertions, 0 deletions
diff --git a/fluent-bit/src/aws/flb_aws_credentials.c b/fluent-bit/src/aws/flb_aws_credentials.c new file mode 100644 index 00000000..850142e2 --- /dev/null +++ b/fluent-bit/src/aws/flb_aws_credentials.c @@ -0,0 +1,862 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2022 The Fluent Bit Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fluent-bit/flb_info.h> +#include <fluent-bit/flb_sds.h> +#include <fluent-bit/flb_http_client.h> +#include <fluent-bit/flb_aws_credentials.h> +#include <fluent-bit/flb_aws_util.h> +#include <fluent-bit/flb_jsmn.h> +#include <fluent-bit/flb_output_plugin.h> + +#include <stdlib.h> +#include <time.h> + +#define FIVE_MINUTES 300 +#define TWELVE_HOURS 43200 + +/* Credentials Environment Variables */ +#define AWS_ACCESS_KEY_ID "AWS_ACCESS_KEY_ID" +#define AWS_SECRET_ACCESS_KEY "AWS_SECRET_ACCESS_KEY" +#define AWS_SESSION_TOKEN "AWS_SESSION_TOKEN" + +#define EKS_POD_EXECUTION_ROLE "EKS_POD_EXECUTION_ROLE" + +/* declarations */ +static struct flb_aws_provider *standard_chain_create(struct flb_config + *config, + struct flb_tls *tls, + char *region, + char *sts_endpoint, + char *proxy, + struct + flb_aws_client_generator + *generator, + int eks_irsa, + char *profile); + + +/* + * The standard credential provider chain: + * 1. Environment variables + * 2. Shared credentials file (AWS Profile) + * 3. EKS OIDC + * 4. EC2 IMDS + * 5. ECS HTTP credentials endpoint + * + * This provider will evaluate each provider in order, returning the result + * from the first provider that returns valid credentials. + * + * Note: Client code should use this provider by default. + */ +struct flb_aws_provider_chain { + struct mk_list sub_providers; + + /* + * The standard chain provider picks the first successful provider and + * then uses it until a call to refresh is made. + */ + struct flb_aws_provider *sub_provider; +}; + +/* + * Iterates through the chain and returns credentials from the first provider + * that successfully returns creds. Caches this provider on the implementation. + */ +struct flb_aws_credentials *get_from_chain(struct flb_aws_provider_chain + *implementation) +{ + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + struct flb_aws_credentials *creds = NULL; + + /* find the first provider that produces a valid set of creds */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + creds = sub_provider->provider_vtable->get_credentials(sub_provider); + if (creds) { + implementation->sub_provider = sub_provider; + return creds; + } + } + + return NULL; +} + +struct flb_aws_credentials *get_credentials_fn_standard_chain(struct + flb_aws_provider + *provider) +{ + struct flb_aws_credentials *creds = NULL; + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = implementation->sub_provider; + + if (sub_provider) { + return sub_provider->provider_vtable->get_credentials(sub_provider); + } + + if (try_lock_provider(provider)) { + creds = get_from_chain(implementation); + unlock_provider(provider); + return creds; + } + + /* + * We failed to lock the provider and sub_provider is unset. This means that + * another co-routine is selecting a provider from the chain. + */ + flb_warn("[aws_credentials] No cached credentials are available and " + "a credential refresh is already in progress. The current " + "co-routine will retry."); + return NULL; +} + +int init_fn_standard_chain(struct flb_aws_provider *provider) +{ + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + int ret = -1; + + if (try_lock_provider(provider)) { + /* find the first provider that indicates successful init */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + ret = sub_provider->provider_vtable->init(sub_provider); + if (ret >= 0) { + implementation->sub_provider = sub_provider; + break; + } + } + unlock_provider(provider); + } + + return ret; +} + +/* + * Client code should only call refresh if there has been an + * error from the AWS APIs indicating creds are expired/invalid. + * Refresh may change the current sub_provider. + */ +int refresh_fn_standard_chain(struct flb_aws_provider *provider) +{ + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + int ret = -1; + + if (try_lock_provider(provider)) { + /* find the first provider that indicates successful refresh */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + ret = sub_provider->provider_vtable->refresh(sub_provider); + if (ret >= 0) { + implementation->sub_provider = sub_provider; + break; + } + } + unlock_provider(provider); + } + + return ret; +} + +void sync_fn_standard_chain(struct flb_aws_provider *provider) +{ + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + + /* set all providers to sync mode */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + sub_provider->provider_vtable->sync(sub_provider); + } +} + +void async_fn_standard_chain(struct flb_aws_provider *provider) +{ + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + + /* set all providers to async mode */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + sub_provider->provider_vtable->async(sub_provider); + } +} + +void upstream_set_fn_standard_chain(struct flb_aws_provider *provider, + struct flb_output_instance *ins) +{ + struct flb_aws_provider_chain *implementation = provider->implementation; + struct flb_aws_provider *sub_provider = NULL; + struct mk_list *tmp; + struct mk_list *head; + + /* set all providers to async mode */ + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, + struct flb_aws_provider, + _head); + sub_provider->provider_vtable->upstream_set(sub_provider, ins); + } +} + +void destroy_fn_standard_chain(struct flb_aws_provider *provider) { + struct flb_aws_provider *sub_provider; + struct flb_aws_provider_chain *implementation; + struct mk_list *tmp; + struct mk_list *head; + + implementation = provider->implementation; + + if (implementation) { + mk_list_foreach_safe(head, tmp, &implementation->sub_providers) { + sub_provider = mk_list_entry(head, struct flb_aws_provider, + _head); + mk_list_del(&sub_provider->_head); + flb_aws_provider_destroy(sub_provider); + } + + flb_free(implementation); + } +} + +static struct flb_aws_provider_vtable standard_chain_provider_vtable = { + .get_credentials = get_credentials_fn_standard_chain, + .init = init_fn_standard_chain, + .refresh = refresh_fn_standard_chain, + .destroy = destroy_fn_standard_chain, + .sync = sync_fn_standard_chain, + .async = async_fn_standard_chain, + .upstream_set = upstream_set_fn_standard_chain, +}; + +struct flb_aws_provider *flb_standard_chain_provider_create(struct flb_config + *config, + struct flb_tls *tls, + char *region, + char *sts_endpoint, + char *proxy, + struct + flb_aws_client_generator + *generator, + char *profile) +{ + struct flb_aws_provider *provider; + struct flb_aws_provider *tmp_provider; + char *eks_pod_role = NULL; + char *session_name; + + eks_pod_role = getenv(EKS_POD_EXECUTION_ROLE); + if (eks_pod_role && strlen(eks_pod_role) > 0) { + /* + * eks fargate + * standard chain will be base provider used to + * assume the EKS_POD_EXECUTION_ROLE + */ + flb_debug("[aws_credentials] Using EKS_POD_EXECUTION_ROLE=%s", eks_pod_role); + tmp_provider = standard_chain_create(config, tls, region, sts_endpoint, + proxy, generator, FLB_FALSE, profile); + + if (!tmp_provider) { + return NULL; + } + + session_name = flb_sts_session_name(); + if (!session_name) { + flb_error("Failed to generate random STS session name"); + flb_aws_provider_destroy(tmp_provider); + return NULL; + } + + provider = flb_sts_provider_create(config, tls, tmp_provider, NULL, + eks_pod_role, session_name, + region, sts_endpoint, + NULL, generator); + if (!provider) { + flb_error("Failed to create EKS Fargate Credential Provider"); + flb_aws_provider_destroy(tmp_provider); + return NULL; + } + /* session name can freed after provider is created */ + flb_free(session_name); + session_name = NULL; + + return provider; + } + + /* standard case- not in EKS Fargate */ + provider = standard_chain_create(config, tls, region, sts_endpoint, + proxy, generator, FLB_TRUE, profile); + return provider; +} + +struct flb_aws_provider *flb_managed_chain_provider_create(struct flb_output_instance + *ins, + struct flb_config + *config, + char *config_key_prefix, + char *proxy, + struct + flb_aws_client_generator + *generator) +{ + flb_sds_t config_key_region; + flb_sds_t config_key_sts_endpoint; + flb_sds_t config_key_role_arn; + flb_sds_t config_key_external_id; + flb_sds_t config_key_profile; + const char *region = NULL; + const char *sts_endpoint = NULL; + const char *role_arn = NULL; + const char *external_id = NULL; + const char *profile = NULL; + char *session_name = NULL; + int key_prefix_len; + int key_max_len; + + /* Provider managed dependencies */ + struct flb_aws_provider *aws_provider = NULL; + struct flb_aws_provider *base_aws_provider = NULL; + struct flb_tls *cred_tls = NULL; + struct flb_tls *sts_tls = NULL; + + /* Config keys */ + key_prefix_len = strlen(config_key_prefix); + key_max_len = key_prefix_len + 12; /* max length of + "region", "sts_endpoint", "role_arn", + "external_id" */ + + /* Evaluate full config keys */ + config_key_region = flb_sds_create_len(config_key_prefix, key_max_len); + strcpy(config_key_region + key_prefix_len, "region"); + config_key_sts_endpoint = flb_sds_create_len(config_key_prefix, key_max_len); + strcpy(config_key_sts_endpoint + key_prefix_len, "sts_endpoint"); + config_key_role_arn = flb_sds_create_len(config_key_prefix, key_max_len); + strcpy(config_key_role_arn + key_prefix_len, "role_arn"); + config_key_external_id = flb_sds_create_len(config_key_prefix, key_max_len); + strcpy(config_key_external_id + key_prefix_len, "external_id"); + config_key_profile = flb_sds_create_len(config_key_prefix, key_max_len); + strcpy(config_key_profile + key_prefix_len, "profile"); + + /* AWS provider needs a separate TLS instance */ + cred_tls = flb_tls_create(FLB_TLS_CLIENT_MODE, + FLB_TRUE, + ins->tls_debug, + ins->tls_vhost, + ins->tls_ca_path, + ins->tls_ca_file, + ins->tls_crt_file, + ins->tls_key_file, + ins->tls_key_passwd); + if (!cred_tls) { + flb_plg_error(ins, "Failed to create TLS instance for AWS Provider"); + flb_errno(); + goto error; + } + + region = flb_output_get_property(config_key_region, ins); + if (!region) { + flb_plg_error(ins, "aws_auth enabled but %s not set", config_key_region); + goto error; + } + + /* Use null sts_endpoint if none provided */ + sts_endpoint = flb_output_get_property(config_key_sts_endpoint, ins); + /* Get the profile from configuration */ + profile = flb_output_get_property(config_key_profile, ins); + aws_provider = flb_standard_chain_provider_create(config, + cred_tls, + (char *) region, + (char *) sts_endpoint, + NULL, + flb_aws_client_generator(), + profile); + if (!aws_provider) { + flb_plg_error(ins, "Failed to create AWS Credential Provider"); + goto error; + } + + role_arn = flb_output_get_property(config_key_role_arn, ins); + if (role_arn) { + /* Use the STS Provider */ + base_aws_provider = aws_provider; + external_id = flb_output_get_property(config_key_external_id, ins); + + session_name = flb_sts_session_name(); + if (!session_name) { + flb_plg_error(ins, "Failed to generate aws iam role " + "session name"); + goto error; + } + + /* STS provider needs yet another separate TLS instance */ + sts_tls = flb_tls_create(FLB_TLS_CLIENT_MODE, + FLB_TRUE, + ins->tls_debug, + ins->tls_vhost, + ins->tls_ca_path, + ins->tls_ca_file, + ins->tls_crt_file, + ins->tls_key_file, + ins->tls_key_passwd); + if (!sts_tls) { + flb_plg_error(ins, "Failed to create TLS instance for AWS STS Credential " + "Provider"); + flb_errno(); + goto error; + } + + aws_provider = flb_sts_provider_create(config, + sts_tls, + base_aws_provider, + (char *) external_id, + (char *) role_arn, + session_name, + (char *) region, + (char *) sts_endpoint, + NULL, + flb_aws_client_generator()); + if (!aws_provider) { + flb_plg_error(ins, "Failed to create AWS STS Credential " + "Provider"); + goto error; + } + } + + /* initialize credentials in sync mode */ + aws_provider->provider_vtable->sync(aws_provider); + aws_provider->provider_vtable->init(aws_provider); + + /* set back to async */ + aws_provider->provider_vtable->async(aws_provider); + + /* store dependencies in aws_provider for managed cleanup */ + aws_provider->base_aws_provider = base_aws_provider; + aws_provider->cred_tls = cred_tls; + aws_provider->sts_tls = sts_tls; + + goto cleanup; + +error: + if (aws_provider) { + /* disconnect dependencies */ + aws_provider->base_aws_provider = NULL; + aws_provider->cred_tls = NULL; + aws_provider->sts_tls = NULL; + /* destroy */ + flb_aws_provider_destroy(aws_provider); + } + /* free dependencies */ + if (base_aws_provider) { + flb_aws_provider_destroy(base_aws_provider); + } + if (cred_tls) { + flb_tls_destroy(cred_tls); + } + if (sts_tls) { + flb_tls_destroy(sts_tls); + } + aws_provider = NULL; + +cleanup: + if (config_key_region) { + flb_sds_destroy(config_key_region); + } + if (config_key_sts_endpoint) { + flb_sds_destroy(config_key_sts_endpoint); + } + if (config_key_role_arn) { + flb_sds_destroy(config_key_role_arn); + } + if (config_key_external_id) { + flb_sds_destroy(config_key_external_id); + } + if (session_name) { + flb_free(session_name); + } + + return aws_provider; +} + +static struct flb_aws_provider *standard_chain_create(struct flb_config + *config, + struct flb_tls *tls, + char *region, + char *sts_endpoint, + char *proxy, + struct + flb_aws_client_generator + *generator, + int eks_irsa, + char *profile) +{ + struct flb_aws_provider *sub_provider; + struct flb_aws_provider *provider; + struct flb_aws_provider_chain *implementation; + + provider = flb_calloc(1, sizeof(struct flb_aws_provider)); + + if (!provider) { + flb_errno(); + return NULL; + } + + pthread_mutex_init(&provider->lock, NULL); + + implementation = flb_calloc(1, sizeof(struct flb_aws_provider_chain)); + + if (!implementation) { + flb_errno(); + flb_free(provider); + return NULL; + } + + provider->provider_vtable = &standard_chain_provider_vtable; + provider->implementation = implementation; + + /* Create chain of providers */ + mk_list_init(&implementation->sub_providers); + + sub_provider = flb_aws_env_provider_create(); + if (!sub_provider) { + /* Env provider will only fail creation if a memory alloc failed */ + flb_aws_provider_destroy(provider); + return NULL; + } + flb_debug("[aws_credentials] Initialized Env Provider in standard chain"); + + mk_list_add(&sub_provider->_head, &implementation->sub_providers); + + flb_debug("[aws_credentials] creating profile %s provider", profile); + sub_provider = flb_profile_provider_create(profile); + if (sub_provider) { + /* Profile provider can fail if HOME env var is not set */; + mk_list_add(&sub_provider->_head, &implementation->sub_providers); + flb_debug("[aws_credentials] Initialized AWS Profile Provider in " + "standard chain"); + } + + if (eks_irsa == FLB_TRUE) { + sub_provider = flb_eks_provider_create(config, tls, region, sts_endpoint, proxy, generator); + if (sub_provider) { + /* EKS provider can fail if we are not running in k8s */; + mk_list_add(&sub_provider->_head, &implementation->sub_providers); + flb_debug("[aws_credentials] Initialized EKS Provider in standard chain"); + } + } + + sub_provider = flb_ecs_provider_create(config, generator); + if (sub_provider) { + /* ECS Provider will fail creation if we are not running in ECS */ + mk_list_add(&sub_provider->_head, &implementation->sub_providers); + flb_debug("[aws_credentials] Initialized ECS Provider in standard chain"); + } + + sub_provider = flb_ec2_provider_create(config, generator); + if (!sub_provider) { + /* EC2 provider will only fail creation if a memory alloc failed */ + flb_aws_provider_destroy(provider); + return NULL; + } + mk_list_add(&sub_provider->_head, &implementation->sub_providers); + flb_debug("[aws_credentials] Initialized EC2 Provider in standard chain"); + + return provider; +} + +/* Environment Provider */ +struct flb_aws_credentials *get_credentials_fn_environment(struct + flb_aws_provider + *provider) +{ + char *access_key = NULL; + char *secret_key = NULL; + char *session_token = NULL; + struct flb_aws_credentials *creds = NULL; + + flb_debug("[aws_credentials] Requesting credentials from the " + "env provider.."); + + access_key = getenv(AWS_ACCESS_KEY_ID); + if (!access_key || strlen(access_key) <= 0) { + return NULL; + } + + secret_key = getenv(AWS_SECRET_ACCESS_KEY); + if (!secret_key || strlen(secret_key) <= 0) { + return NULL; + } + + creds = flb_calloc(1, sizeof(struct flb_aws_credentials)); + if (!creds) { + flb_errno(); + return NULL; + } + + creds->access_key_id = flb_sds_create(access_key); + if (!creds->access_key_id) { + flb_aws_credentials_destroy(creds); + flb_errno(); + return NULL; + } + + creds->secret_access_key = flb_sds_create(secret_key); + if (!creds->secret_access_key) { + flb_aws_credentials_destroy(creds); + flb_errno(); + return NULL; + } + + session_token = getenv(AWS_SESSION_TOKEN); + if (session_token && strlen(session_token) > 0) { + creds->session_token = flb_sds_create(session_token); + if (!creds->session_token) { + flb_aws_credentials_destroy(creds); + flb_errno(); + return NULL; + } + } else { + creds->session_token = NULL; + } + + return creds; + +} + +int refresh_env(struct flb_aws_provider *provider) +{ + char *access_key = NULL; + char *secret_key = NULL; + + access_key = getenv(AWS_ACCESS_KEY_ID); + if (!access_key || strlen(access_key) <= 0) { + return -1; + } + + secret_key = getenv(AWS_SECRET_ACCESS_KEY); + if (!secret_key || strlen(secret_key) <= 0) { + return -1; + } + + return 0; +} + +/* + * For the env provider, refresh simply checks if the environment + * variables are available. + */ +int refresh_fn_environment(struct flb_aws_provider *provider) +{ + flb_debug("[aws_credentials] Refresh called on the env provider"); + + return refresh_env(provider); +} + +int init_fn_environment(struct flb_aws_provider *provider) +{ + flb_debug("[aws_credentials] Init called on the env provider"); + + return refresh_env(provider); +} + +/* + * sync and async are no-ops for the env provider because it does not make + * network IO calls + */ +void sync_fn_environment(struct flb_aws_provider *provider) +{ + return; +} + +void async_fn_environment(struct flb_aws_provider *provider) +{ + return; +} + +void upstream_set_fn_environment(struct flb_aws_provider *provider, + struct flb_output_instance *ins) +{ + return; +} + +/* Destroy is a no-op for the env provider */ +void destroy_fn_environment(struct flb_aws_provider *provider) { + return; +} + +static struct flb_aws_provider_vtable environment_provider_vtable = { + .get_credentials = get_credentials_fn_environment, + .init = init_fn_environment, + .refresh = refresh_fn_environment, + .destroy = destroy_fn_environment, + .sync = sync_fn_environment, + .async = async_fn_environment, + .upstream_set = upstream_set_fn_environment, +}; + +struct flb_aws_provider *flb_aws_env_provider_create() { + struct flb_aws_provider *provider = flb_calloc(1, sizeof( + struct flb_aws_provider)); + + if (!provider) { + flb_errno(); + return NULL; + } + + provider->provider_vtable = &environment_provider_vtable; + provider->implementation = NULL; + + return provider; +} + + +void flb_aws_credentials_destroy(struct flb_aws_credentials *creds) +{ + if (creds) { + if (creds->access_key_id) { + flb_sds_destroy(creds->access_key_id); + } + if (creds->secret_access_key) { + flb_sds_destroy(creds->secret_access_key); + } + if (creds->session_token) { + flb_sds_destroy(creds->session_token); + } + + flb_free(creds); + } +} + +void flb_aws_provider_destroy(struct flb_aws_provider *provider) +{ + if (provider) { + if (provider->implementation) { + provider->provider_vtable->destroy(provider); + } + + pthread_mutex_destroy(&provider->lock); + + /* free managed dependencies */ + if (provider->base_aws_provider) { + flb_aws_provider_destroy(provider->base_aws_provider); + } + if (provider->cred_tls) { + flb_tls_destroy(provider->cred_tls); + } + if (provider->sts_tls) { + flb_tls_destroy(provider->sts_tls); + } + + flb_free(provider); + } +} + +time_t timestamp_to_epoch(const char *timestamp) +{ + struct tm tm = {0}; + time_t seconds; + int r; + + r = sscanf(timestamp, "%d-%d-%dT%d:%d:%dZ", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + if (r != 6) { + return -1; + } + + tm.tm_year -= 1900; + tm.tm_mon -= 1; + tm.tm_isdst = -1; + seconds = timegm(&tm); + if (seconds < 0) { + return -1; + } + + return seconds; +} + +time_t flb_aws_cred_expiration(const char *timestamp) +{ + time_t now; + time_t expiration = timestamp_to_epoch(timestamp); + if (expiration < 0) { + flb_warn("[aws_credentials] Could not parse expiration: %s", timestamp); + return -1; + } + /* + * Sanity check - expiration should be ~10 minutes to 12 hours in the future + * (> 12 hours is impossible with the current APIs and would likely indicate + * a bug in how this code processes timestamps.) + */ + now = time(NULL); + if (expiration < (now + FIVE_MINUTES)) { + flb_warn("[aws_credentials] Credential expiration '%s' is less than " + "5 minutes in the future.", + timestamp); + } + if (expiration > (now + TWELVE_HOURS)) { + flb_warn("[aws_credentials] Credential expiration '%s' is greater than " + "12 hours in the future. This should not be possible.", + timestamp); + } + return expiration; +} + +/* + * Fluent Bit is now multi-threaded and asynchonous with coros. + * The trylock prevents deadlock, and protects the provider + * when a cred refresh happens. The refresh frees and + * sets the shared cred cache, a double free could occur + * if two threads do it at the same exact time. + */ + +/* Like a traditional try lock- it does not block if the lock is not obtained */ +int try_lock_provider(struct flb_aws_provider *provider) +{ + int ret = 0; + ret = pthread_mutex_trylock(&provider->lock); + if (ret != 0) { + return FLB_FALSE; + } + return FLB_TRUE; +} + +void unlock_provider(struct flb_aws_provider *provider) +{ + pthread_mutex_unlock(&provider->lock); +} |