From 9c28fad7484a66442663579008f1687579c8920a Mon Sep 17 00:00:00 2001 From: adiforluls Date: Fri, 22 Sep 2023 12:13:46 +0530 Subject: [PATCH 01/10] out_oracle_log_analytics: add instance_principal and oke_workload_identity auth modes Signed-off-by: adiforluls --- .../out_oracle_log_analytics/CMakeLists.txt | 1 + plugins/out_oracle_log_analytics/oci_client.c | 689 ++++++++++++++++ plugins/out_oracle_log_analytics/oci_client.h | 84 ++ plugins/out_oracle_log_analytics/oci_logan.c | 240 ++---- plugins/out_oracle_log_analytics/oci_logan.h | 56 ++ .../out_oracle_log_analytics/oci_logan_conf.c | 746 +++++++++++++++++- .../out_oracle_log_analytics/oci_logan_conf.h | 4 + 7 files changed, 1642 insertions(+), 178 deletions(-) create mode 100644 plugins/out_oracle_log_analytics/oci_client.c create mode 100644 plugins/out_oracle_log_analytics/oci_client.h diff --git a/plugins/out_oracle_log_analytics/CMakeLists.txt b/plugins/out_oracle_log_analytics/CMakeLists.txt index 81f971a9501..b582f06cb44 100644 --- a/plugins/out_oracle_log_analytics/CMakeLists.txt +++ b/plugins/out_oracle_log_analytics/CMakeLists.txt @@ -1,6 +1,7 @@ set(src oci_logan.c oci_logan_conf.c + oci_client.c ) FLB_PLUGIN(out_oracle_log_analytics "${src}" "") diff --git a/plugins/out_oracle_log_analytics/oci_client.c b/plugins/out_oracle_log_analytics/oci_client.c new file mode 100644 index 00000000000..09cb5934ec1 --- /dev/null +++ b/plugins/out_oracle_log_analytics/oci_client.c @@ -0,0 +1,689 @@ +// +// Created by Aditya Bharadwaj on 22/09/23. +// + +#include "oci_client.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, + flb_sds_t signing_string) +{ + int len = 0, ret; + size_t outlen; + flb_sds_t signature; + unsigned char sha256_buf[32] = { 0 }; + unsigned char sig[256] = { 0 }; + size_t sig_len = sizeof(sig); + + ret = flb_hash_simple(FLB_HASH_SHA256, + (unsigned char*) signing_string, + flb_sds_len(signing_string), + sha256_buf, sizeof(sha256_buf)); + + if(ret != FLB_CRYPTO_SUCCESS) { + // flb_plg_error(ctx->ins, "error generating hash buffer"); + return NULL; + } + + ret = flb_crypto_sign_simple(FLB_CRYPTO_PRIVATE_KEY, + FLB_CRYPTO_PADDING_PKCS1, + FLB_HASH_SHA256, + (unsigned char *) private_key, + flb_sds_len(private_key), + sha256_buf, sizeof(sha256_buf), + sig, &sig_len); + + + if (ret != FLB_CRYPTO_SUCCESS) { + // flb_plg_error(ctx->ins, "error signing SHA256"); + return NULL; + } + + signature = flb_sds_create_size(512); + if (!signature) { + flb_errno(); + return NULL; + } + + /* base 64 encode */ + len = flb_sds_alloc(signature) - 1; + flb_base64_encode((unsigned char*) signature, len, &outlen, sig, + sizeof(sig)); + signature[outlen] = '\0'; + flb_sds_len_set(signature, outlen); + + return signature; +} + +flb_sds_t get_date(void) +{ + + flb_sds_t rfc1123date; + time_t t; + size_t size; + struct tm tm = { 0 }; + + /* Format Date */ + rfc1123date = flb_sds_create_size(32); + if (!rfc1123date) { + flb_errno(); + return NULL; + } + + t = time(NULL); + if (!gmtime_r(&t, &tm)) { + flb_errno(); + flb_sds_destroy(rfc1123date); + return NULL; + } + size = strftime(rfc1123date, flb_sds_alloc(rfc1123date) - 1, + "%a, %d %b %Y %H:%M:%S GMT", &tm); + if (size <= 0) { + flb_errno(); + flb_sds_destroy(rfc1123date); + return NULL; + } + flb_sds_len_set(rfc1123date, size); + return rfc1123date; +} + +flb_sds_t add_header_and_signing(struct flb_http_client *c, + flb_sds_t signing_str, + const char *header, + int headersize, + const char *val, int val_size) +{ + if (!signing_str) { + return NULL; + } + + flb_http_add_header(c, header, headersize, val, val_size); + + signing_str = flb_sds_cat(signing_str, "\n", 1); + signing_str = flb_sds_cat(signing_str, header, headersize); + signing_str = flb_sds_cat(signing_str, ": ", 2); + signing_str = flb_sds_cat(signing_str, val, val_size); + + return signing_str; +} + +/* + * Authorization: Signature version="1",keyId="//", + * algorithm="rsa-sha256",headers="(request-target) date x-content-sha256 content-type content-length", + * signature="signature" + */ +flb_sds_t create_authorization_header_content(flb_sds_t signature, + flb_sds_t key_id) +{ + flb_sds_t content; + + content = flb_sds_create_size(1024*10); + content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE_VERSION, + sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_SIGN_KEYID, + sizeof(FLB_OCI_SIGN_KEYID) - 1); + content = flb_sds_cat(content, "=\"", 2); + content = flb_sds_cat(content, key_id, flb_sds_len(key_id)); + content = flb_sds_cat(content, "\",", 2); + content = flb_sds_cat(content, FLB_OCI_SIGN_ALGORITHM, + sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_SIGN_HEADERS, + sizeof(FLB_OCI_SIGN_HEADERS) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE, + sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); + content = flb_sds_cat(content, "=\"", 2); + content = flb_sds_cat(content, signature, flb_sds_len(signature)); + content = flb_sds_cat(content, "\"", 1); + + return content; +} + +flb_sds_t create_fed_authorization_header_content(flb_sds_t signature, + flb_sds_t key_id) +{ + flb_sds_t content; + + content = flb_sds_create_size(512); + content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE_VERSION, + sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_SIGN_KEYID, + sizeof(FLB_OCI_SIGN_KEYID) - 1); + content = flb_sds_cat(content, "=\"", 2); + content = flb_sds_cat(content, key_id, flb_sds_len(key_id)); + content = flb_sds_cat(content, "\",", 2); + content = flb_sds_cat(content, FLB_OCI_SIGN_ALGORITHM, + sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_FED_SIGN_HEADERS, + sizeof(FLB_OCI_FED_SIGN_HEADERS) - 1); + content = flb_sds_cat(content, ",", 1); + content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE, + sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); + content = flb_sds_cat(content, "=\"", 2); + content = flb_sds_cat(content, signature, flb_sds_len(signature)); + content = flb_sds_cat(content, "\"", 1); + + return content; +} + +flb_sds_t refresh_cert(struct flb_upstream *u, + flb_sds_t cert_url, + struct flb_output_instance *ins) +{ + flb_sds_t cert = NULL; + struct flb_connection *u_conn; + struct flb_http_client *c; + int ret = 0; + size_t b_sent; + u_conn = flb_upstream_conn_get(u); + if (!u_conn) { + flb_errno(); + return NULL; + } + + c = flb_http_client(u_conn, FLB_HTTP_GET, cert_url, NULL, 0, + NULL, 0, NULL, 0); + + if (!c) { + flb_errno(); + flb_upstream_conn_release(u_conn); + return NULL; + } + + flb_http_strip_port_from_host(c); + flb_http_buffer_size(c, 0); + flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); + + ret = flb_http_do(c, &b_sent); + + if (ret != 0) { + flb_errno(); + flb_plg_error(ins, "http do error"); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + if (c->resp.status != 200 && c->resp.status != 204 && c->resp.status != 201) { + flb_errno(); + flb_plg_info(ins, "request header = %s", c->header_buf); + flb_plg_error(ins, "request was not successful with status = %d payload = %s url = %s", + c->resp.status, c->resp.payload, cert_url); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + cert = flb_sds_create_len(c->resp.payload, c->resp.payload_size); + + if (!cert) { + flb_errno(); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return cert; +} + +// finish this func +flb_sds_t get_tenancy_id_from_certificate(X509 *cert) +{ + flb_sds_t t_id = NULL; + const unsigned char *str; + char* x; + + X509_NAME *subj = X509_get_subject_name(cert); + + for (int i = 0; i < X509_NAME_entry_count(subj); i++) { + X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, i); + ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); + str = ASN1_STRING_get0_data(d); + x = strstr((const char *) str, "opc-tenant:"); + if (x) { + break; + } + } + + t_id = flb_sds_create((const char*) str + 11); + + return t_id; +} + +char* sanitize_certificate_string(flb_sds_t cert_pem) +{ + // i2d_X509() + char sanitized[strlen(cert_pem) + 1]; + strcpy(sanitized, cert_pem); + char c_start[] = "-----BEGIN CERTIFICATE-----"; + size_t c_st_len = strlen(c_start); + char c_end[] = "-----END CERTIFICATE-----"; + char k_start[] = "-----BEGIN PUBLIC KEY-----"; + size_t k_st_len = strlen(k_start); + char k_end[] = "-----END PUBLIC KEY-----"; + char *p = NULL, *q = NULL, *ans, *tmp, *a; + + p = strstr(sanitized, c_start); + q = strstr(sanitized, c_end); + if (p && q) { + *q = '\0'; + tmp = p + c_st_len + 1; + } + else { + p = strstr(sanitized, k_start); + q = strstr(sanitized, k_end); + *q = '\0'; + tmp = p + k_st_len; + } + ans = flb_malloc(strlen(sanitized) + sizeof(char)); + a = ans; + while(*tmp != '\0') + { + if(*tmp != '\t' && *tmp != '\n') { + *a++ = *tmp++; + } + else { + ++tmp; + } + } + *a = '\0'; + + return ans; + +} + +void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len) +{ + char *l; + for(size_t i=0; i < len-1; i++) { + l = (char*) (3*i + ((intptr_t) writebuf)); + sprintf(l, "%02x:", readbuf[i]); + } + + l = (char*) (3*(len - 1) + ((intptr_t) writebuf)); + sprintf(l, "%02x", readbuf[len - 1]); +} + +flb_sds_t fingerprint(X509 *cert) +{ + // i2d_X509() + flb_sds_t fingerprint = NULL; + const EVP_MD *digest; + unsigned char md[SHA_DIGEST_LENGTH]; + char buf[3*SHA_DIGEST_LENGTH+1]; + unsigned int n; + + digest = EVP_get_digestbyname("sha1"); + X509_digest(cert, digest, md, &n); + + colon_separated_fingerprint(md, (void *) buf, (size_t) SHA_DIGEST_LENGTH); + + fingerprint = flb_sds_create_len(buf, 3*SHA_DIGEST_LENGTH); + return fingerprint; +} + +int session_key_supplier(flb_sds_t *priv_key, + flb_sds_t *pub_key, + struct flb_output_instance *ins) +{ + // Key generation + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + EVP_PKEY* key = NULL; + BIO *pri, *pub; + int priKeyLen; + int pubKeyLen; + char* priKeyStr; + char* pubKeyStr; + int ret; + BIGNUM *bne = NULL; + + bne = BN_new(); + ret = BN_set_word(bne, RSA_EXP); + if (ret != 1) { + return -1; + } + EVP_PKEY_keygen_init(ctx); + EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bne); + EVP_PKEY_keygen(ctx, &key); + EVP_PKEY_CTX_free(ctx); + + // Serialize to string + pri = BIO_new(BIO_s_mem()); + pub = BIO_new(BIO_s_mem()); + PEM_write_bio_PrivateKey_traditional(pri, key, NULL, NULL, 0, 0, NULL); + PEM_write_bio_PUBKEY(pub, key); + + priKeyLen = BIO_pending(pri); + pubKeyLen = BIO_pending(pub); + priKeyStr = flb_malloc(priKeyLen); + pubKeyStr = flb_malloc(pubKeyLen); + BIO_read(pri, priKeyStr, priKeyLen); + BIO_read(pub, pubKeyStr, pubKeyLen); + priKeyStr[priKeyLen] = '\0'; + pubKeyStr[pubKeyLen] = '\0'; + // flb_plg_info(ins, "private_key = %s", priKeyStr); + // flb_plg_info(ins, "pub_key = %s", pubKeyStr); + + *priv_key = flb_sds_create_len((const char *) priKeyStr, priKeyLen); + *pub_key = flb_sds_create_len((const char *)pubKeyStr, pubKeyLen); + + BIO_free(pri); + BIO_free(pub); + flb_free(priKeyStr); + flb_free(pubKeyStr); + BN_free(bne); + + return 0; +} + +X509 *get_cert_from_string(flb_sds_t cert_pem) +{ + X509 *cert; + BIO* certBio = BIO_new(BIO_s_mem()); + BIO_write(certBio, cert_pem, (int) flb_sds_len(cert_pem)); + cert = PEM_read_bio_X509(certBio, NULL, NULL, NULL); + + BIO_free(certBio); + return cert; +} + +flb_sds_t get_region(struct flb_upstream *u, + flb_sds_t region_url, + struct flb_hash_table *ht) +{ + flb_sds_t region; + char* temp_region = NULL; + struct flb_connection *u_conn; + struct flb_http_client *c; + size_t b_sent, temp_sz; + int ret; + + // TODO: construct region uri + u_conn = flb_upstream_conn_get(u); + if (!u_conn) { + flb_errno(); + return NULL; + } + + c = flb_http_client(u_conn, FLB_HTTP_GET, region_url, + NULL, 0, NULL, 0, NULL, 0); + if (!c) { + flb_errno(); + return NULL; + } + + flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); + + ret = flb_http_do(c, &b_sent); + + if (ret != 0) { + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + if (c->resp.status != 200 && c->resp.status != 201 && + c->resp.status != 204) { + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + ret = flb_hash_table_get(ht, mk_string_tolower(c->resp.payload), + (int)c->resp.payload_size, + (void *)&temp_region, + &temp_sz); + if (ret < 0) { + temp_region = c->resp.payload; + temp_sz = c->resp.payload_size; + } + + region = flb_sds_create_len(temp_region, + (int) temp_sz); + + return region; +} + +flb_sds_t parse_token(char *response, + size_t response_len) +{ + int tok_size = 32, ret, i; + jsmn_parser parser; + jsmntok_t *t; + jsmntok_t *tokens; + char *key; + char *val; + int key_len; + int val_len; + flb_sds_t token = NULL; + + jsmn_init(&parser); + + tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); + if (!tokens) { + flb_errno(); + return NULL; + } + + ret = jsmn_parse(&parser, response, response_len, tokens, tok_size); + + if (ret<=0) { + flb_free(tokens); + return NULL; + } + tok_size = ret; + + /* Parse JSON tokens */ + for (i = 0; i < tok_size; i++) { + t = &tokens[i]; + + if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { + break; + } + + if (t->type != JSMN_STRING) { + continue; + } + + key = response + t->start; + key_len = (t->end - t->start); + + i++; + t = &tokens[i]; + val = response + t->start; + val_len = (t->end - t->start); + + if (val_len < 1) { + continue; + } + + if ((key_len == sizeof(FLB_OCI_TOKEN) - 1) + && strncasecmp(key, FLB_OCI_TOKEN, + sizeof(FLB_OCI_TOKEN) - 1) == 0) { + // code + token = flb_sds_create_len(val, val_len); + if (!token) { + flb_free(tokens); + return NULL; + } + break; + } + } + + flb_free(tokens); + return token; +} + +static const char *jwt_decode_payload(const char *src, + char **bufplainp) { + char *converted_src; + char *payload = NULL; + + const char *errstr = NULL; + + int i, padding, len; + + int payload_len; + int nbytesdecoded; + + int payloads_start = 0; + int payloads_end = 0; + + len = (int)strlen(src); + converted_src = flb_malloc(len + 4); + + for (i = 0; i < len; i++) { + switch (src[i]) { + case '-': + converted_src[i] = '+'; + break; + + case '_': + converted_src[i] = '/'; + break; + + case '.': + if (payloads_start == 0) + payloads_start = i + 1; + else { + if (payloads_end > 0) { + errstr = + "The token is invalid with more " + "than 2 delimiters"; + goto done; + } + payloads_end = i; + } + /* FALLTHRU */ + + default: + converted_src[i] = src[i]; + } + } + + if (payloads_start == 0 || payloads_end == 0) { + errstr = "The token is invalid with less than 2 delimiters"; + goto done; + } + + payload_len = payloads_end - payloads_start; + payload = flb_malloc(payload_len + 4); + strncpy(payload, (converted_src + payloads_start), payload_len); + + padding = 4 - (payload_len % 4); + if (padding < 4) { + while (padding--) + payload[payload_len++] = '='; + } + + nbytesdecoded = ((payload_len + 3) / 4) * 3; + *bufplainp = flb_malloc(nbytesdecoded + 1); + + if (EVP_DecodeBlock((uint8_t *)(*bufplainp), (uint8_t *)payload, + (int)payload_len) == -1) { + errstr = "Failed to decode base64 payload"; + } + + done: + flb_free(payload); + flb_free(converted_src); + return errstr; +} + +const char* get_token_exp(flb_sds_t token_string, + time_t *exp, + struct flb_output_instance *ins) +{ + char *payload = NULL; + const char* err_str = NULL; + + err_str = jwt_decode_payload(token_string, &payload); + // flb_plg_info(ins, "jwt payload = %s", payload); + + if (err_str != NULL) { + return err_str; + } + + int tok_size = 256, ret, i; + jsmn_parser parser; + jsmntok_t *t; + jsmntok_t *tokens; + char *key; + char *val; + int key_len; + int val_len; + flb_sds_t token = NULL; + + jsmn_init(&parser); + + tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); + if (!tokens) { + flb_errno(); + return NULL; + } + + ret = jsmn_parse(&parser, payload, strlen(payload), tokens, tok_size); + + if (ret<=0) { + flb_free(tokens); + return NULL; + } + tok_size = ret; + + /* Parse JSON tokens */ + for (i = 0; i < tok_size; i++) { + t = &tokens[i]; + + if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { + break; + } + + if (t->type != JSMN_STRING) { + continue; + } + + key = payload + t->start; + key_len = (t->end - t->start); + + i++; + t = &tokens[i]; + val = payload + t->start; + val_len = (t->end - t->start); + + if (val_len < 1) { + continue; + } + + // flb_plg_info(ins, "sectoken %s: %s", key, val); + if ((key_len == 3) + && strncasecmp(key, "exp", + 3) == 0) { + // code + flb_plg_info(ins, "fetched exp time = %s", val); + *exp = atol(val); + break; + } + } + + flb_free(tokens); + return err_str; +} diff --git a/plugins/out_oracle_log_analytics/oci_client.h b/plugins/out_oracle_log_analytics/oci_client.h new file mode 100644 index 00000000000..66bfaaede7c --- /dev/null +++ b/plugins/out_oracle_log_analytics/oci_client.h @@ -0,0 +1,84 @@ +// +// Created by Aditya Bharadwaj on 22/09/23. +// + + +#ifndef FLUENT_BIT_OUT_OCI_LOGAN_OCI_CLIENT_H +#define FLUENT_BIT_OUT_OCI_LOGAN_OCI_CLIENT_H + +#define FLB_OCI_TOKEN "token" +#define RSA_EXP 65537 + +#define FLB_OCI_HEADER_REQUEST_TARGET "(request-target)" +#define FLB_OCI_HEADER_USER_AGENT "User-Agent" +#define FLB_OCI_HEADER_USER_AGENT_VAL "Fluent-Bit" +#define FLB_OCI_HEADER_CONTENT_TYPE "content-type" +#define FLB_OCI_HEADER_CONTENT_TYPE_VAL "application/octet-stream" +#define FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL "application/json" +#define FLB_OCI_HEADER_X_CONTENT_SHA256 "x-content-sha256" +#define FLB_OCI_HEADER_CONTENT_LENGTH "content-length" +#define FLB_OCI_HEADER_HOST "host" +#define FLB_OCI_HEADER_DATE "date" +#define FLB_OCI_HEADER_AUTH "Authorization" +#define FLB_OCI_PAYLOAD_TYPE "payloadType" + +#define FLB_OCI_SIGN_SIGNATURE_VERSION "Signature version=\"1\"" +#define FLB_OCI_SIGN_KEYID "keyId" +#define FLB_OCI_SIGN_ALGORITHM "algorithm=\"rsa-sha256\"" + +#define FLB_OCI_SIGN_HEADERS "headers=\"" \ + FLB_OCI_HEADER_REQUEST_TARGET " " \ + FLB_OCI_HEADER_HOST " " \ + FLB_OCI_HEADER_DATE " " \ + FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ + FLB_OCI_HEADER_CONTENT_TYPE " " \ + FLB_OCI_HEADER_CONTENT_LENGTH "\"" + +#define FLB_OCI_SIGN_SIGNATURE "signature" +#define FLB_OCI_FED_SIGN_HEADERS "headers=\"" \ + FLB_OCI_HEADER_REQUEST_TARGET " " \ + FLB_OCI_HEADER_DATE " " \ + FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ + FLB_OCI_HEADER_CONTENT_TYPE " " \ + FLB_OCI_HEADER_CONTENT_LENGTH "\"" + + +#endif //FLUENT_BIT_PLUGINS_OUT_OCI_LOGAN_OCI_CLIENT_H_ + +#include +#include +#include +#include +#include +#include +#include + +flb_sds_t refresh_cert(struct flb_upstream *u, flb_sds_t cert_url, + struct flb_output_instance *ins); +flb_sds_t get_tenancy_id_from_certificate(X509 *cert); +char* sanitize_certificate_string(flb_sds_t cert_pem); +void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len); +flb_sds_t fingerprint(X509 *cert); +int session_key_supplier(flb_sds_t *priv_key, + flb_sds_t *pub_key, + struct flb_output_instance *ins); +X509 *get_cert_from_string(flb_sds_t cert_pem); +flb_sds_t get_region(struct flb_upstream *u, flb_sds_t region_url, + struct flb_hash_table *ht); +flb_sds_t parse_token(char *response, + size_t response_len); +flb_sds_t add_header_and_signing(struct flb_http_client *c, + flb_sds_t signing_str, + const char *header, + int headersize, + const char *val, int val_size); +flb_sds_t get_date(void); +flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, + flb_sds_t signing_string); +flb_sds_t create_authorization_header_content(flb_sds_t signature, + flb_sds_t key_id); +const char* get_token_exp(flb_sds_t token_string, + time_t *exp, + struct flb_output_instance *ins); +flb_sds_t create_fed_authorization_header_content(flb_sds_t signature, + flb_sds_t key_id); diff --git a/plugins/out_oracle_log_analytics/oci_logan.c b/plugins/out_oracle_log_analytics/oci_logan.c index 630812e2d28..d9a3935830d 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.c +++ b/plugins/out_oracle_log_analytics/oci_logan.c @@ -40,7 +40,7 @@ static int check_config_from_record(msgpack_object key, - char *name, int len) + char *name, int len) { if (key.type != MSGPACK_OBJECT_STR) { return FLB_FALSE; @@ -54,145 +54,12 @@ static int check_config_from_record(msgpack_object key, return memcmp(key.via.str.ptr, name, len) == 0; } -/* - * Authorization: Signature version="1",keyId="//", - * algorithm="rsa-sha256",headers="(request-target) date x-content-sha256 content-type content-length", - * signature="signature" - */ -static flb_sds_t create_authorization_header_content(struct flb_oci_logan *ctx, - flb_sds_t signature) -{ - flb_sds_t content; - - content = flb_sds_create_size(512); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_SIGNATURE_VERSION, - sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); - flb_sds_cat_safe(&content, ",", 1); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_KEYID, - sizeof(FLB_OCI_SIGN_KEYID) - 1); - flb_sds_cat_safe(&content, "=\"", 2); - flb_sds_cat_safe(&content, ctx->key_id, flb_sds_len(ctx->key_id)); - flb_sds_cat_safe(&content, "\",", 2); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_ALGORITHM, - sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); - flb_sds_cat_safe(&content, ",", 1); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_HEADERS, - sizeof(FLB_OCI_SIGN_HEADERS) - 1); - flb_sds_cat_safe(&content, ",", 1); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_SIGNATURE, - sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); - flb_sds_cat_safe(&content, "=\"", 2); - flb_sds_cat_safe(&content, signature, flb_sds_len(signature)); - flb_sds_cat_safe(&content, "\"", 1); - - return content; -} - -static flb_sds_t create_base64_sha256_signature(struct flb_oci_logan *ctx, - flb_sds_t signing_string) -{ - int len = 0, ret; - size_t outlen; - flb_sds_t signature; - unsigned char sha256_buf[32] = { 0 }; - unsigned char sig[256] = { 0 }; - size_t sig_len = sizeof(sig); - - ret = flb_hash_simple(FLB_HASH_SHA256, - (unsigned char*) signing_string, - flb_sds_len(signing_string), - sha256_buf, sizeof(sha256_buf)); - - if(ret != FLB_CRYPTO_SUCCESS) { - flb_plg_error(ctx->ins, "error generating hash buffer"); - return NULL; - } - - ret = flb_crypto_sign_simple(FLB_CRYPTO_PRIVATE_KEY, - FLB_CRYPTO_PADDING_PKCS1, - FLB_HASH_SHA256, - (unsigned char *) ctx->private_key, - flb_sds_len(ctx->private_key), - sha256_buf, sizeof(sha256_buf), - sig, &sig_len); - - - if (ret != FLB_CRYPTO_SUCCESS) { - flb_plg_error(ctx->ins, "error signing SHA256"); - return NULL; - } - - signature = flb_sds_create_size(512); - if (!signature) { - flb_errno(); - return NULL; - } - - /* base 64 encode */ - len = flb_sds_alloc(signature) - 1; - flb_base64_encode((unsigned char*) signature, len, &outlen, sig, - sizeof(sig)); - signature[outlen] = '\0'; - flb_sds_len_set(signature, outlen); - - return signature; -} - -static flb_sds_t get_date(void) -{ - - flb_sds_t rfc1123date; - time_t t; - size_t size; - struct tm tm = { 0 }; - - /* Format Date */ - rfc1123date = flb_sds_create_size(32); - if (!rfc1123date) { - flb_errno(); - return NULL; - } - - t = time(NULL); - if (!gmtime_r(&t, &tm)) { - flb_errno(); - flb_sds_destroy(rfc1123date); - return NULL; - } - size = strftime(rfc1123date, flb_sds_alloc(rfc1123date) - 1, - "%a, %d %b %Y %H:%M:%S GMT", &tm); - if (size <= 0) { - flb_errno(); - flb_sds_destroy(rfc1123date); - return NULL; - } - flb_sds_len_set(rfc1123date, size); - return rfc1123date; -} - -static flb_sds_t add_header_and_signing(struct flb_http_client *c, - flb_sds_t signing_str, const char *header, int headersize, - const char *val, int val_size) -{ - if (!signing_str) { - return NULL; - } - - flb_http_add_header(c, header, headersize, val, val_size); - - flb_sds_cat_safe(&signing_str, "\n", 1); - flb_sds_cat_safe(&signing_str, header, headersize); - flb_sds_cat_safe(&signing_str, ": ", 2); - flb_sds_cat_safe(&signing_str, val, val_size); - - return signing_str; -} - static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, flb_sds_t json, flb_sds_t hostname, int port, flb_sds_t uri) { int ret = -1; flb_sds_t tmp_sds = NULL; + flb_sds_t tmp_sds_1 = NULL; flb_sds_t signing_str = NULL; flb_sds_t rfc1123date = NULL; flb_sds_t encoded_uri = NULL; @@ -217,22 +84,22 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - /* Add (requeset-target) to signing string */ + // Add (requeset-target) to signing string encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); if (!encoded_uri) { flb_errno(); goto error_label; } - flb_sds_cat_safe(&signing_str, FLB_OCI_HEADER_REQUEST_TARGET, - sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); - flb_sds_cat_safe(&signing_str, ": post ", sizeof(": post ") - 1); - flb_sds_cat_safe(&signing_str, encoded_uri, - flb_sds_len(encoded_uri)); + signing_str = flb_sds_cat(signing_str, FLB_OCI_HEADER_REQUEST_TARGET, + sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); + signing_str = flb_sds_cat(signing_str, ": post ", sizeof(": post ") - 1); + signing_str = flb_sds_cat(signing_str, encoded_uri, + flb_sds_len(encoded_uri)); - /* Add Host to Header */ + // Add Host to Header if (((c->flags & FLB_IO_TLS) && c->port == 443) || (!(c->flags & FLB_IO_TLS) && c->port == 80)) { - /* default port */ + // default port tmp_ref = flb_sds_copy(tmp_sds, c->host, strlen(c->host)); } else { @@ -253,7 +120,7 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - /* Add Date header */ + // Add Date header rfc1123date = get_date(); if (!rfc1123date) { flb_plg_error(ctx->ins, "cannot compose temporary date header"); @@ -267,7 +134,8 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - /* Add x-content-sha256 Header */ + tmp_sds_1 = flb_sds_create_size(1024); + // Add x-content-sha256 Header ret = flb_hash_simple(FLB_HASH_SHA256, (unsigned char*) json, flb_sds_len(json), @@ -278,22 +146,22 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - flb_base64_encode((unsigned char*) tmp_sds, flb_sds_len(tmp_sds) - 1, + flb_base64_encode((unsigned char*) tmp_sds_1, flb_sds_len(tmp_sds_1) - 1, &tmp_len, sha256_buf, sizeof(sha256_buf)); - tmp_sds[tmp_len] = '\0'; - flb_sds_len_set(tmp_sds, tmp_len); + tmp_sds_1[tmp_len] = '\0'; + flb_sds_len_set(tmp_sds_1, tmp_len); signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_X_CONTENT_SHA256, - sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds, - flb_sds_len(tmp_sds)); + sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds_1, + flb_sds_len(tmp_sds_1)); if (!signing_str) { flb_plg_error(ctx->ins, "cannot compose signing string"); goto error_label; } - /* Add content-Type */ + // Add content-Type signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, FLB_OCI_HEADER_CONTENT_TYPE_VAL, @@ -303,7 +171,7 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - /* Add content-Length */ + // Add content-Length tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", (int) flb_sds_len(json)); flb_sds_len_set(tmp_sds, tmp_len); @@ -315,29 +183,34 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, goto error_label; } - /* Add Authorization header */ - signature = create_base64_sha256_signature(ctx, signing_str); + flb_plg_info(ctx->ins, "signing str = %s", signing_str); + // Add Authorization header + signature = create_base64_sha256_signature(ctx->private_key, signing_str); if (!signature) { flb_plg_error(ctx->ins, "cannot compose signing signature"); goto error_label; } - auth_header_str = create_authorization_header_content(ctx, signature); + flb_plg_info(ctx->ins, "signature = %s", signature); + + auth_header_str = create_authorization_header_content( signature, ctx->key_id); if (!auth_header_str) { flb_plg_error(ctx->ins, "cannot compose authorization header"); goto error_label; } + flb_plg_info(ctx->ins, "auth header str = %s", auth_header_str); + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, auth_header_str, flb_sds_len(auth_header_str)); - /* User-Agent */ + // User-Agent flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, FLB_OCI_HEADER_USER_AGENT_VAL, sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); - /* Accept */ + // Accept flb_http_add_header(c, "Accept", 6, "*/*", 3); ret = 0; @@ -346,6 +219,9 @@ static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, if (tmp_sds) { flb_sds_destroy(tmp_sds); } + if (tmp_sds_1) { + flb_sds_destroy(tmp_sds_1); + } if (signing_str) { flb_sds_destroy(signing_str); } @@ -1189,6 +1065,31 @@ static void cb_oci_logan_flush(struct flb_event_chunk *event_chunk, struct flb_oci_logan *ctx = out_context; int ret = -1; + if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { + ret = refresh_security_token(ctx, config); + if (ret != 0) { + flb_errno(); + // flb_oci_logan_conf_destroy(ctx); + FLB_OUTPUT_RETURN(FLB_RETRY); + } + ctx->private_key = ctx->fed_client->private_key; + ctx->region = ctx->fed_client->region; + flb_sds_snprintf(&ctx->key_id, flb_sds_alloc(ctx->key_id), + "ST$%s", ctx->fed_client->security_token); + flb_plg_info(ctx->ins, "key_id = %s", ctx->key_id); + } + if (strcasecmp(ctx->auth_type, WORKLOAD_IDENTITY) == 0) { + ret = refresh_oke_workload_security_token(ctx, config); + if (ret != 0) { + flb_errno(); + flb_plg_error(ctx->ins, + "failed to refresh RPST token from proxymux endpoint"); + FLB_OUTPUT_RETURN(FLB_RETRY); + } + ctx->private_key = ctx->fed_client->private_key; + } + + ret = total_flush(event_chunk, out_flush, ins, out_context, config); @@ -1287,6 +1188,31 @@ static struct flb_config_map config_map[] = { 0, FLB_TRUE, offsetof(struct flb_oci_logan, proxy), "define proxy if required, in http://host:port format, supports only http protocol" }, + { + FLB_CONFIG_MAP_STR, "auth_type", INSTANCE_PRINCIPAL, + 0, FLB_TRUE, offsetof(struct flb_oci_logan, auth_type), + "authentication type of the plugin" + }, + { + FLB_CONFIG_MAP_STR, "region", NULL, + 0, FLB_TRUE, offsetof(struct flb_oci_logan, region), + "OCI region. This field is only applicable for workload identity authentication" + }, + { + FLB_CONFIG_MAP_STR, "oke_sa_ca_file", FLB_OKE_DEFAULT_SA_CERT_PATH, + 0, FLB_TRUE, offsetof(struct flb_oci_logan, oke_sa_ca_file), + "Kubernetes TLS CA file" + }, + + /* Kubernetes Token file */ + { + FLB_CONFIG_MAP_STR, "oke_sa_token_file", FLB_OKE_TOKEN_PATH, + 0, FLB_TRUE, offsetof(struct flb_oci_logan, oke_sa_token_file), + "Kubernetes authorization token file" + }, + + + {0} }; diff --git a/plugins/out_oracle_log_analytics/oci_logan.h b/plugins/out_oracle_log_analytics/oci_logan.h index 7cc9e75f4a1..549ff9fa8cd 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.h +++ b/plugins/out_oracle_log_analytics/oci_logan.h @@ -115,6 +115,15 @@ #define FLB_OCI_HEADER_AUTH "Authorization" #define FLB_OCI_PAYLOAD_TYPE "payloadType" +#define INSTANCE_PRINCIPAL "instance_principal" +#define USER_PRINCIPAL "user_principal" +#define WORKLOAD_IDENTITY "workload_identity" + +#define FLB_OKE_DEFAULT_SA_CERT_PATH "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" +#define FLB_OKE_TOKEN_PATH "/var/run/secrets/kubernetes.io/serviceaccount/token" + + + /* For OCI signing */ #define FLB_OCI_PARAM_TENANCY "tenancy" @@ -150,12 +159,47 @@ #define FLB_OCI_ERROR_CODE_TOO_MANY_REQUESTS "TooManyRequests" #define FLB_OCI_ERROR_CODE_INTERNAL_SERVER_ERROR "InternalServerError" +#define OCI_FEDERATION_REQUEST_PAYLOAD "{\"certificate\":\"%s\",\"publicKey\":\"%s\", \"intermediateCertificates\":[\"%s\"]}" +#define OCI_OKE_PROXYMUX_PAYLOAD "{\"podKey\":\"%s\"}" + +#define METADATA_HOST_BASE "169.254.169.254" +#define GET_REGION_URL "/opc/v2/instance/region" +#define GET_REGION_INFO_URL "/opc/v2/instance/regionInfo/" +#define LEAF_CERTIFICATE_URL "/opc/v2/identity/cert.pem" +#define LEAF_CERTIFICATE_PRIVATE_KEY_URL "/opc/v2/identity/key.pem" +#define INTERMEDIATE_CERTIFICATE_URL "/opc/v2/identity/intermediate.pem" + + #include #include #include #include #include +#include "oci_client.h" + +struct federation_client { + struct flb_upstream *u; + flb_sds_t region; + flb_sds_t tenancy_id; + struct cert_retriever *leaf_cert_ret; + struct cert_retriever *intermediate_cert_ret; + // session key supplier + flb_sds_t private_key; + flb_sds_t public_key; + flb_sds_t key_id; + flb_sds_t security_token; + time_t expire; + pthread_mutex_t lock; +}; + +struct cert_retriever { + struct flb_upstream *u; + flb_sds_t cert_pem; + X509 *cert; + flb_sds_t private_key_pem; +}; + struct metadata_obj { flb_sds_t key; flb_sds_t val; @@ -175,8 +219,13 @@ struct flb_oci_logan { flb_sds_t profile_name; int oci_config_in_record; flb_sds_t uri; + flb_sds_t auth_type; struct flb_upstream *u; + + struct flb_upstream *cert_u; + struct flb_upstream *fed_u; + flb_sds_t proxy; char *proxy_host; int proxy_port; @@ -208,6 +257,13 @@ struct flb_oci_logan { /* For OCI signing */ flb_sds_t key_id; // tenancy/user/key_fingerprint flb_sds_t private_key; + flb_sds_t oke_sa_ca_file; + flb_sds_t oke_sa_token_file; + + struct federation_client *fed_client; + + struct flb_hash_table *region_table; + struct flb_output_instance *ins; diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.c b/plugins/out_oracle_log_analytics/oci_logan_conf.c index a3980318465..1dd3596b9a2 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.c +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.c @@ -36,6 +36,466 @@ #include "oci_logan.h" #include "oci_logan_conf.h" +char* short_names[] = { + "yny\0", + "hyd\0", + "mel\0", + "bom\0", + "kix\0", + "icn\0", + "syd\0", + "nrt\0", + "yul\0", + "yyz\0", + "ams\0", + "fra\0", + "zrh\0", + "jed\0", + "dxb\0", + "gru\0", + "cwl\0", + "lhr\0", + "iad\0", + "phx\0", + "sjc\0", + "vcp\0", + "scl\0", + "mtz\0", + "mrs\0", + "sin\0", + "auh\0", + "lin\0", + "arn\0", + "jnb\0", + "cdg\0", + "qro\0", + "mad\0", + "ord\0", + "lfi\0", + "luf\0", + "ric\0", + "pia\0", + "tus\0", + "ltn\0", + "brs\0", + "nja\0", + "ukb\0", + "mct\0", + "wga\0", + "bgy\0", + "mxp\0", + "snn\0", + "dtm\0", + "dus\0", + "ork\0", + "vll\0", + "str\0", + "beg\0", + NULL +}; + +char *long_names[] = { + "ap-chuncheon-1\0", + "ap-hyderabad-1\0", + "ap-melbourne-1\0", + "ap-mumbai-1\0", + "ap-osaka-1\0", + "ap-seoul-1\0", + "ap-sydney-1\0", + "ap-tokyo-1\0", + "ca-montreal-1\0", + "ca-toronto-1\0", + "eu-amsterdam-1\0", + "eu-frankfurt-1\0", + "eu-zurich-1\0", + "me-jeddah-1\0", + "me-dubai-1\0", + "sa-saopaulo-1\0", + "uk-cardiff-1\0", + "uk-london-1\0", + "us-ashburn-1\0", + "us-phoenix-1\0", + "us-sanjose-1\0", + "sa-vinhedo-1\0", + "sa-santiago-1\0", + "il-jerusalem-1\0", + "eu-marseille-1\0", + "ap-singapore-1\0", + "me-abudhabi-1\0", + "eu-milan-1\0", + "eu-stockholm-1\0", + "af-johannesburg-1\0", + "eu-paris-1\0", + "mx-queretaro-1\0", + "eu-madrid-1\0", + "us-chicago-1\0", + "us-langley-1\0", + "us-luke-1\0", + "us-gov-ashburn-1\0", + "us-gov-chicago-1\0", + "us-gov-phoenix-1\0", + "uk-gov-london-1\0", + "uk-gov-cardiff-1\0", + "ap-chiyoda-1\0", + "ap-ibaraki-1\0", + "me-dcc-muscat-1\0", + "ap-dcc-canberra-1\0", + "eu-dcc-milan-1\0", + "eu-dcc-milan-2\0", + "eu-dcc-dublin-2\0", + "eu-dcc-rating-2\0", + "eu-dcc-rating-1\0", + "eu-dcc-dublin-1\0", + "eu-madrid-2\0", + "eu-frankfurt-2\0", + "eu-jovanovac-1\0", + NULL +}; + +static void build_region_table(struct flb_oci_logan *ctx) { + ctx->region_table = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE, 100, 0); + int i; + for(i = 0; short_names[i] != NULL; i++) { + flb_hash_table_add(ctx->region_table, + short_names[i], + strlen(short_names[i]), + long_names[i], + strlen(long_names[i])); + } + +} + +static int build_federation_client_headers(struct flb_oci_logan *ctx, + struct flb_http_client *c, + flb_sds_t json, + flb_sds_t uri) +{ + int ret = -1; + flb_sds_t tmp_sds = NULL; + flb_sds_t signing_str = NULL; + flb_sds_t rfc1123date = NULL; + flb_sds_t encoded_uri = NULL; + flb_sds_t signature = NULL; + flb_sds_t auth_header_str = NULL; + + flb_sds_t tmp_ref = NULL; + + size_t tmp_len = 0; + + unsigned char sha256_buf[32] = { 0 }; + + tmp_sds = flb_sds_create_size(512); + if (!tmp_sds) { + flb_errno(); + goto error_label; + } + + signing_str = flb_sds_create_size(1024); + if (!signing_str) { + flb_errno(); + goto error_label; + } + + // Add (requeset-target) to signing string + encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); + if (!encoded_uri) { + flb_errno(); + goto error_label; + } + signing_str = flb_sds_cat(signing_str, FLB_OCI_HEADER_REQUEST_TARGET, + sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); + signing_str = flb_sds_cat(signing_str, ": post ", sizeof(": post ") - 1); + signing_str = flb_sds_cat(signing_str, encoded_uri, + flb_sds_len(encoded_uri)); + + // Add Date header + rfc1123date = get_date(); + if (!rfc1123date) { + flb_plg_error(ctx->ins, "cannot compose temporary date header"); + goto error_label; + } + signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_DATE, + sizeof(FLB_OCI_HEADER_DATE) - 1, rfc1123date, + flb_sds_len(rfc1123date)); + if (!signing_str) { + flb_plg_error(ctx->ins, "cannot compose signing string"); + goto error_label; + } + + // Add x-content-sha256 Header + ret = flb_hash_simple(FLB_HASH_SHA256, + (unsigned char*) json, + flb_sds_len(json), + sha256_buf, sizeof(sha256_buf)); + + if (ret != FLB_CRYPTO_SUCCESS) { + flb_plg_error(ctx->ins, "error forming hash buffer for x-content-sha256 Header"); + goto error_label; + } + + flb_base64_encode((unsigned char*) tmp_sds, flb_sds_len(tmp_sds) - 1, + &tmp_len, sha256_buf, sizeof(sha256_buf)); + + tmp_sds[tmp_len] = '\0'; + flb_sds_len_set(tmp_sds, tmp_len); + + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_X_CONTENT_SHA256, + sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds, + flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ctx->ins, "cannot compose signing string"); + goto error_label; + } + + // Add content-Type + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, + FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL) - 1); + if (!signing_str) { + flb_plg_error(ctx->ins, "cannot compose signing string"); + goto error_label; + } + + // Add content-Length + tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", + (int) strlen(json)); + flb_sds_len_set(tmp_sds, tmp_len); + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_LENGTH, sizeof(FLB_OCI_HEADER_CONTENT_LENGTH) - 1, + tmp_sds, flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ctx->ins, "cannot compose signing string"); + goto error_label; + } + + // Add Authorization header + signature = create_base64_sha256_signature(ctx->fed_client->leaf_cert_ret->private_key_pem, + signing_str); + if (!signature) { + flb_plg_error(ctx->ins, "cannot compose signing signature"); + goto error_label; + } + + auth_header_str = create_fed_authorization_header_content(signature, ctx->fed_client->key_id); + if (!auth_header_str) { + flb_plg_error(ctx->ins, "cannot compose authorization header"); + goto error_label; + } + + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, + auth_header_str, flb_sds_len(auth_header_str)); + + // User-Agent + flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, + sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, + FLB_OCI_HEADER_USER_AGENT_VAL, + sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); + + // Accept + flb_http_add_header(c, "Accept", 6, "*/*", 3); + + ret = 0; + + error_label: + if (tmp_sds) { + flb_sds_destroy(tmp_sds); + } + if (signing_str) { + flb_sds_destroy(signing_str); + } + if (rfc1123date) { + flb_sds_destroy(rfc1123date); + } + if (encoded_uri) { + flb_sds_destroy(encoded_uri); + } + if (signature) { + flb_sds_destroy(signature); + } + if (auth_header_str) { + flb_sds_destroy(auth_header_str); + } + return ret; + +} + +int refresh_security_token(struct flb_oci_logan *ctx, + struct flb_config *config) +{ + flb_sds_t region; + flb_sds_t host; + flb_sds_t fed_uri; + char* err; + struct flb_upstream *upstream; + struct flb_connection *u_conn; + struct flb_http_client *c; + struct flb_kv *kv; + struct mk_list *tmp; + struct mk_list *head; + char *s_leaf_cert, *s_inter_cert, *s_pub_key; + int ret = -1, sz; + time_t now; + size_t b_sent; + flb_sds_t json; + if (ctx->fed_client && ctx->fed_client->expire) { + now = time(NULL); + if (ctx->fed_client->expire > now) { + return 0; + } + } + if (!ctx->fed_client) { + ctx->fed_client = flb_calloc(1, sizeof(struct federation_client)); + } + if (!ctx->fed_client->leaf_cert_ret) { + ctx->fed_client->leaf_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); + } + if (!ctx->fed_client->intermediate_cert_ret) { + ctx->fed_client->intermediate_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); + } + + ctx->fed_client->leaf_cert_ret->cert_pem = refresh_cert(ctx->cert_u, + LEAF_CERTIFICATE_URL, + ctx->ins); + if (!ctx->fed_client->leaf_cert_ret->cert_pem) { + return -1; + } + ctx->fed_client->leaf_cert_ret->private_key_pem = refresh_cert(ctx->cert_u, + LEAF_CERTIFICATE_PRIVATE_KEY_URL, + ctx->ins); + if (!ctx->fed_client->leaf_cert_ret->private_key_pem) { + return -1; + } + ctx->fed_client->leaf_cert_ret->cert = get_cert_from_string(ctx->fed_client->leaf_cert_ret->cert_pem); + + ctx->fed_client->intermediate_cert_ret->cert_pem = refresh_cert(ctx->cert_u, + INTERMEDIATE_CERTIFICATE_URL, + ctx->ins); + if (!ctx->fed_client->intermediate_cert_ret->cert_pem) { + return -1; + } + + region = get_region(ctx->cert_u, GET_REGION_URL, ctx->region_table); + flb_plg_info(ctx->ins, "region = %s", region); + ctx->fed_client->region = region; + host = flb_sds_create_size(512); + flb_sds_snprintf(&host, flb_sds_alloc(host), "auth.%s.oci.oraclecloud.com", region); + if (!ctx->fed_u) { + upstream = flb_upstream_create(config, host, 443, + FLB_IO_TLS, ctx->ins->tls); + if (!upstream) { + return -1; + } + + ctx->fed_u = upstream; + } + ctx->fed_client->tenancy_id = get_tenancy_id_from_certificate(ctx->fed_client->leaf_cert_ret->cert); + ret = session_key_supplier(&ctx->fed_client->private_key, + &ctx->fed_client->public_key, + ctx->ins); + if (ret != 0) { + flb_plg_error(ctx->ins, "failed to create session key pair"); + return -1; + } + + ctx->fed_client->key_id = flb_sds_create_size(512); + flb_sds_snprintf(&ctx->fed_client->key_id, flb_sds_alloc(ctx->fed_client->key_id), + "%s/fed-x509/%s", ctx->fed_client->tenancy_id, fingerprint(ctx->fed_client->leaf_cert_ret->cert)); + // flb_plg_info(ctx->ins, "fed client key_id = %s", ctx->fed_client->key_id); + + // TODO: build headers + u_conn = flb_upstream_conn_get(ctx->fed_u); + if (!u_conn) { + return -1; + } + + s_leaf_cert = sanitize_certificate_string(ctx->fed_client->leaf_cert_ret->cert_pem); + // flb_plg_info(ctx->ins, "sanitized leaf cert: %s", s_leaf_cert); + s_pub_key = sanitize_certificate_string(ctx->fed_client->public_key); + // flb_plg_info(ctx->ins, "pub key: %s", s_pub_key); + s_inter_cert = sanitize_certificate_string(ctx->fed_client->intermediate_cert_ret->cert_pem); + // flb_plg_info(ctx->ins, "sanitized inter cert: %s", s_inter_cert); + sz = strlen(s_leaf_cert) + strlen(s_pub_key) + strlen(s_inter_cert); + json = flb_sds_create_size(sz + 1000); + flb_sds_snprintf(&json, flb_sds_alloc(json), + OCI_FEDERATION_REQUEST_PAYLOAD, + s_leaf_cert, + s_pub_key, + s_inter_cert); + // flb_plg_info(ctx->ins, "fed client payload = %s", json); + + fed_uri = flb_sds_create_len("/v1/x509", 8); + c = flb_http_client(u_conn, FLB_HTTP_POST, fed_uri, + json, flb_sds_len(json), + NULL, 0, NULL, 0); + c->allow_dup_headers = FLB_FALSE; + + build_federation_client_headers(ctx, c, json, fed_uri); + + /* + mk_list_foreach_safe(head, tmp, &c->headers) { + kv = mk_list_entry(head, struct flb_kv, _head); + if (flb_sds_casecmp(kv->key, "host", 4) == 0) { + flb_kv_item_destroy(kv); + break; + } + } + */ + + + ret = flb_http_do(c, &b_sent); + if (ret != 0) { + flb_plg_error(ctx->ins, "http do error"); + flb_sds_destroy(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + if (c->resp.status != 200) { + flb_plg_error(ctx->ins, "http status = %d, response = %s, header = %s", + c->resp.status, c->resp.payload, c->header_buf); + flb_sds_destroy(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + ctx->fed_client->security_token = parse_token(c->resp.payload, + c->resp.payload_size); + flb_plg_info(ctx->ins, "security token = %s", ctx->fed_client->security_token); + + err = get_token_exp(ctx->fed_client->security_token, &ctx->fed_client->expire, ctx->ins); + if (err) { + flb_plg_error(ctx->ins, "token error = %s",err); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_free(fed_uri); + flb_sds_destroy(json); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + flb_plg_info(ctx->ins, "token expiration time = %ld", ctx->fed_client->expire); + flb_free(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return 0; + +} + static int create_pk_context(flb_sds_t filepath, const char *key_passphrase, struct flb_oci_logan *ctx) { @@ -94,6 +554,196 @@ static int create_pk_context(flb_sds_t filepath, const char *key_passphrase, return 0; } +static int file_to_buffer(const char *path, + char **out_buf, size_t *out_size) +{ + int ret; + char *buf; + ssize_t bytes; + FILE *fp; + struct stat st; + + if (!(fp = fopen(path, "r"))) { + return -1; + } + + ret = stat(path, &st); + if (ret == -1) { + flb_errno(); + fclose(fp); + return -1; + } + + buf = flb_calloc(1, (st.st_size + 1)); + if (!buf) { + flb_errno(); + fclose(fp); + return -1; + } + + bytes = fread(buf, st.st_size, 1, fp); + if (bytes < 1) { + flb_free(buf); + fclose(fp); + return -1; + } + + fclose(fp); + + *out_buf = buf; + *out_size = st.st_size; + + return 0; +} + +int refresh_oke_workload_security_token(struct flb_oci_logan *ctx, + struct flb_config *config) +{ + char* tmp, *host; + const char* err = NULL; + char buf[1024*8] = {0}; + size_t o_len; + int port = 12250, ret; + struct flb_tls *tls; + struct flb_http_client *c; + struct flb_connection *u_conn; + flb_sds_t auth_header; + char *token = NULL; + size_t tk_size; + flb_sds_t json; + flb_sds_t uri; + size_t b_sent; + time_t now; + + if (ctx->fed_client && ctx->fed_client->expire) { + now = time(NULL); + if (ctx->fed_client->expire > now) { + return 0; + } + } + + if (!ctx->fed_client) { + ctx->fed_client = flb_calloc(1, sizeof(struct federation_client)); + } + + /* + tmp = getenv("OCI_RESOURCE_PRINCIPAL_REGION"); + if (!tmp) { + flb_plg_error(ctx->ins, "Not a valid region"); + flb_sds_destroy(sa_cert_path); + return -1; + } + ctx->fed_client->region = flb_sds_create_len(tmp, strlen(tmp)); + */ + session_key_supplier(&ctx->fed_client->private_key, + &ctx->fed_client->public_key, + ctx->ins); + host = getenv("KUBERNETES_SERVICE_HOST"); + if (!host) { + flb_plg_error(ctx->ins, "Host not found"); + return -1; + } + if (!ctx->fed_u) { + tls = flb_tls_create(FLB_TLS_CLIENT_MODE, + 0, + 1, + NULL, + NULL, + ctx->oke_sa_ca_file, + NULL, + NULL, + NULL); + ctx->fed_u = flb_upstream_create(config, host, port, FLB_IO_TLS, tls); + } + + ret = file_to_buffer(ctx->oke_sa_token_file, &token, &tk_size); + if (ret != 0) { + flb_errno(); + flb_plg_error(ctx->ins, "failed to load kubernetes service account token"); + return -1; + } + + char *s_pub_key = sanitize_certificate_string(ctx->fed_client->public_key); + json = flb_sds_create_size(1024*4); + flb_sds_snprintf(&json, flb_sds_alloc(json), + OCI_OKE_PROXYMUX_PAYLOAD, s_pub_key); + uri = flb_sds_create_len("/resourcePrincipalSessionTokens", + sizeof("/resourcePrincipalSessionTokens") - 1); + + u_conn = flb_upstream_conn_get(ctx->fed_u); + if (!u_conn) { + flb_errno(); + flb_plg_error(ctx->ins, + "failed to establish connection with kubernetes upstream"); + return -1; + } + c = flb_http_client(u_conn, FLB_HTTP_POST, uri, json, flb_sds_len(json), NULL, 0, NULL, 0); + if (!c) { + flb_errno(); + flb_plg_error(ctx->ins, + "failed to create http client"); + flb_upstream_conn_release(u_conn); + return -1; + } + auth_header = flb_sds_create_size(1024*4); + ret = flb_sds_snprintf(&auth_header, flb_sds_alloc(auth_header), "Bearer %s", token); + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, + sizeof(FLB_OCI_HEADER_AUTH) - 1, + auth_header, + ret); + flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, + sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, + "Fluent-Bit", 10); + flb_http_add_header(c, FLB_OCI_HEADER_CONTENT_TYPE, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, + FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL) - 1); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + ret = flb_http_do(c, &b_sent); + if (ret != 0) { + flb_plg_error(ctx->ins, "http do error"); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + if (c->resp.status != 200) { + flb_plg_info(ctx->ins, "request body = %s", json); + flb_plg_info(ctx->ins, "request header = %s", c->header_buf); + flb_plg_error(ctx->ins, + "HTTP Status = %d, payload = %s", + c->resp.status, c->resp.payload); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + + c->resp.payload++; + c->resp.payload[strlen(c->resp.payload) - 1] = '\0'; + flb_base64_decode((unsigned char*)buf, + sizeof(buf), + &o_len, + (unsigned char*) c->resp.payload, + strlen(c->resp.payload)); + ctx->key_id = parse_token(buf, strlen(buf)); + err = get_token_exp(ctx->key_id + 3, &ctx->fed_client->expire, ctx->ins); + + if (err != NULL) { + flb_plg_error(ctx->ins, + "failed to extract token expiration time"); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + flb_plg_info(ctx->ins, "token expiration time = %ld", ctx->fed_client->expire); + // decode jwt token stored in buf + // Make the request and fetch the security token + + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + + return 0; +} + static int load_oci_credentials(struct flb_oci_logan *ctx) { flb_sds_t content; @@ -287,6 +937,10 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, return NULL; } + if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { + ctx->cert_u = flb_upstream_create(config, METADATA_HOST_BASE, 80, FLB_IO_TCP, NULL); + } + if (ctx->oci_config_in_record == FLB_FALSE) { if (ctx->oci_la_log_source_name == NULL || ctx->oci_la_log_group_id == NULL) { @@ -317,18 +971,20 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, } } - if (!ctx->config_file_location) { - flb_errno(); - flb_plg_error(ctx->ins, "config file location is required"); - flb_oci_logan_conf_destroy(ctx); - return NULL; - } + if (strcasecmp(ctx->auth_type, USER_PRINCIPAL) == 0) { + if (!ctx->config_file_location) { + flb_errno(); + flb_plg_error(ctx->ins, "config file location is required"); + flb_oci_logan_conf_destroy(ctx); + return NULL; + } - ret = load_oci_credentials(ctx); - if(ret != 0) { - flb_errno(); - flb_oci_logan_conf_destroy(ctx); - return NULL; + ret = load_oci_credentials(ctx); + if (ret != 0) { + flb_errno(); + flb_oci_logan_conf_destroy(ctx); + return NULL; + } } if (ins->host.name) { @@ -358,18 +1014,19 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, ctx->namespace); } - - - if (create_pk_context(ctx->key_file, NULL, ctx) < 0) { - flb_plg_error(ctx->ins, "failed to create pk context"); - flb_oci_logan_conf_destroy(ctx); - return NULL; + if (strcasecmp(ctx->auth_type, USER_PRINCIPAL) == 0) { + if (create_pk_context(ctx->key_file, NULL, ctx) < 0) { + flb_plg_error(ctx->ins, "failed to create pk context"); + flb_oci_logan_conf_destroy(ctx); + return NULL; + } } - - ctx->key_id = flb_sds_create_size(512); - flb_sds_snprintf(&ctx->key_id, flb_sds_alloc(ctx->key_id), - "%s/%s/%s", ctx->tenancy, ctx->user, ctx->key_fingerprint); + ctx->key_id = flb_sds_create_size(512*8); + if (strcasecmp(ctx->auth_type, USER_PRINCIPAL) == 0) { + flb_sds_snprintf(&ctx->key_id, flb_sds_alloc(ctx->key_id), + "%s/%s/%s", ctx->tenancy, ctx->user, ctx->key_fingerprint); + } /* Check if SSL/TLS is enabled */ @@ -453,11 +1110,58 @@ static void metadata_fields_destroy(struct flb_oci_logan *ctx) } +int flb_cert_ret_destroy(struct cert_retriever *cert_ret) { + if (cert_ret->cert_pem) { + flb_sds_destroy(cert_ret->cert_pem); + } + if (cert_ret->private_key_pem) { + flb_sds_destroy(cert_ret->private_key_pem); + } + if (cert_ret->cert) { + X509_free(cert_ret->cert); + } +} +int flb_fed_client_destroy(struct federation_client *fd) { + if (fd->security_token) { + flb_sds_destroy(fd->security_token); + } + if (fd->leaf_cert_ret) { + flb_cert_ret_destroy(fd->leaf_cert_ret); + } + if (fd->key_id) { + flb_sds_destroy(fd->key_id); + } + if (fd->public_key) { + flb_sds_destroy(fd->public_key); + } + if (fd->tenancy_id) { + flb_sds_destroy(fd->tenancy_id); + } + if (fd->private_key) { + flb_sds_destroy(fd->private_key); + } + if (fd->intermediate_cert_ret) { + flb_cert_ret_destroy(fd->intermediate_cert_ret); + } + if (fd->region) { + flb_sds_destroy(fd->region); + } +} + int flb_oci_logan_conf_destroy(struct flb_oci_logan *ctx) { if(ctx == NULL) { return 0; } + if (ctx->fed_client) { + flb_fed_client_destroy(ctx->fed_client); + } + if (ctx->cert_u) { + flb_upstream_destroy(ctx->cert_u); + } + if (ctx->fed_u) { + flb_upstream_destroy(ctx->fed_u); + } if (ctx->private_key) { flb_sds_destroy(ctx->private_key); } diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.h b/plugins/out_oracle_log_analytics/oci_logan_conf.h index a11832b0a82..9e13f521c0d 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.h +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.h @@ -30,5 +30,9 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, struct flb_config *config); int flb_oci_logan_conf_destroy(struct flb_oci_logan *ctx); +int refresh_security_token(struct flb_oci_logan *ctx, + struct flb_config *config); +int refresh_oke_workload_security_token(struct flb_oci_logan *ctx, + struct flb_config *config); #endif From 4ef17755a481bccb68814bc1308fe3528f43a0bc Mon Sep 17 00:00:00 2001 From: adiforluls Date: Fri, 22 Sep 2023 12:14:53 +0530 Subject: [PATCH 02/10] add copyrights to new files Signed-off-by: adiforluls --- plugins/out_oracle_log_analytics/oci_client.c | 23 ++++++++++++++++--- plugins/out_oracle_log_analytics/oci_client.h | 22 +++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/plugins/out_oracle_log_analytics/oci_client.c b/plugins/out_oracle_log_analytics/oci_client.c index 09cb5934ec1..bbb47b7f857 100644 --- a/plugins/out_oracle_log_analytics/oci_client.c +++ b/plugins/out_oracle_log_analytics/oci_client.c @@ -1,6 +1,23 @@ -// -// Created by Aditya Bharadwaj on 22/09/23. -// +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 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 "oci_client.h" diff --git a/plugins/out_oracle_log_analytics/oci_client.h b/plugins/out_oracle_log_analytics/oci_client.h index 66bfaaede7c..4aa78cd5b72 100644 --- a/plugins/out_oracle_log_analytics/oci_client.h +++ b/plugins/out_oracle_log_analytics/oci_client.h @@ -1,6 +1,22 @@ -// -// Created by Aditya Bharadwaj on 22/09/23. -// +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 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. + */ + #ifndef FLUENT_BIT_OUT_OCI_LOGAN_OCI_CLIENT_H From a215630d5c513741453827027b326a440d6e3542 Mon Sep 17 00:00:00 2001 From: adiforluls Date: Fri, 22 Sep 2023 12:32:36 +0530 Subject: [PATCH 03/10] fix style Signed-off-by: adiforluls --- plugins/out_oracle_log_analytics/oci_client.c | 7 ++++--- plugins/out_oracle_log_analytics/oci_logan_conf.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/out_oracle_log_analytics/oci_client.c b/plugins/out_oracle_log_analytics/oci_client.c index bbb47b7f857..4dcaed5d9bb 100644 --- a/plugins/out_oracle_log_analytics/oci_client.c +++ b/plugins/out_oracle_log_analytics/oci_client.c @@ -264,12 +264,13 @@ flb_sds_t refresh_cert(struct flb_upstream *u, flb_sds_t get_tenancy_id_from_certificate(X509 *cert) { flb_sds_t t_id = NULL; + int i; const unsigned char *str; char* x; X509_NAME *subj = X509_get_subject_name(cert); - for (int i = 0; i < X509_NAME_entry_count(subj); i++) { + for (i = 0; i < X509_NAME_entry_count(subj); i++) { X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, i); ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); str = ASN1_STRING_get0_data(d); @@ -329,7 +330,8 @@ char* sanitize_certificate_string(flb_sds_t cert_pem) void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len) { char *l; - for(size_t i=0; i < len-1; i++) { + size_t i; + for(i=0; i < len-1; i++) { l = (char*) (3*i + ((intptr_t) writebuf)); sprintf(l, "%02x:", readbuf[i]); } @@ -648,7 +650,6 @@ const char* get_token_exp(flb_sds_t token_string, char *val; int key_len; int val_len; - flb_sds_t token = NULL; jsmn_init(&parser); diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.c b/plugins/out_oracle_log_analytics/oci_logan_conf.c index 1dd3596b9a2..80bb3cb6c8a 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.c +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.c @@ -178,8 +178,6 @@ static int build_federation_client_headers(struct flb_oci_logan *ctx, flb_sds_t signature = NULL; flb_sds_t auth_header_str = NULL; - flb_sds_t tmp_ref = NULL; - size_t tmp_len = 0; unsigned char sha256_buf[32] = { 0 }; @@ -937,6 +935,8 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, return NULL; } + build_region_table(ctx); + if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { ctx->cert_u = flb_upstream_create(config, METADATA_HOST_BASE, 80, FLB_IO_TCP, NULL); } From 21da7e21c02f1d5d0b09ff12074ef79f364ecb3c Mon Sep 17 00:00:00 2001 From: adiforluls Date: Tue, 26 Sep 2023 10:51:02 +0530 Subject: [PATCH 04/10] refactor upstream creation Signed-off-by: adiforluls --- plugins/out_oracle_log_analytics/oci_logan.c | 10 +- plugins/out_oracle_log_analytics/oci_logan.h | 2 +- .../out_oracle_log_analytics/oci_logan_conf.c | 151 ++++++++++-------- .../out_oracle_log_analytics/oci_logan_conf.h | 3 + 4 files changed, 99 insertions(+), 67 deletions(-) diff --git a/plugins/out_oracle_log_analytics/oci_logan.c b/plugins/out_oracle_log_analytics/oci_logan.c index d9a3935830d..68bd75985b8 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.c +++ b/plugins/out_oracle_log_analytics/oci_logan.c @@ -1064,19 +1064,25 @@ static void cb_oci_logan_flush(struct flb_event_chunk *event_chunk, { struct flb_oci_logan *ctx = out_context; int ret = -1; + flb_sds_t host = NULL; if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { ret = refresh_security_token(ctx, config); if (ret != 0) { flb_errno(); - // flb_oci_logan_conf_destroy(ctx); FLB_OUTPUT_RETURN(FLB_RETRY); } ctx->private_key = ctx->fed_client->private_key; ctx->region = ctx->fed_client->region; flb_sds_snprintf(&ctx->key_id, flb_sds_alloc(ctx->key_id), "ST$%s", ctx->fed_client->security_token); - flb_plg_info(ctx->ins, "key_id = %s", ctx->key_id); + ret = set_upstream_ctx(ctx, ctx->ins, config); + if (ret != 0) { + flb_errno(); + flb_plg_error(ctx->ins, "cannot create Upstream context"); + FLB_OUTPUT_RETURN(FLB_ERROR); + } + flb_plg_debug(ctx->ins, "key_id = %s", ctx->key_id); } if (strcasecmp(ctx->auth_type, WORKLOAD_IDENTITY) == 0) { ret = refresh_oke_workload_security_token(ctx, config); diff --git a/plugins/out_oracle_log_analytics/oci_logan.h b/plugins/out_oracle_log_analytics/oci_logan.h index 549ff9fa8cd..9f07d9c2694 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.h +++ b/plugins/out_oracle_log_analytics/oci_logan.h @@ -117,7 +117,7 @@ #define INSTANCE_PRINCIPAL "instance_principal" #define USER_PRINCIPAL "user_principal" -#define WORKLOAD_IDENTITY "workload_identity" +#define WORKLOAD_IDENTITY "oke_workload_identity" #define FLB_OKE_DEFAULT_SA_CERT_PATH "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" #define FLB_OKE_TOKEN_PATH "/var/run/secrets/kubernetes.io/serviceaccount/token" diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.c b/plugins/out_oracle_log_analytics/oci_logan_conf.c index 80bb3cb6c8a..0feb656b168 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.c +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.c @@ -907,6 +907,88 @@ static int log_event_metadata_create(struct flb_oci_logan *ctx) return 0; } + +int set_upstream_ctx(struct flb_oci_logan *ctx, + struct flb_output_instance *ins, + struct flb_config *config) +{ + struct flb_upstream *upstream; + flb_sds_t host = NULL; + int io_flags = 0, default_port; + const char *tmp; + int ret = 0; + char *protocol = NULL; + char *p_host = NULL; + char *p_port = NULL; + char *p_uri = NULL; + + if (ins->host.name) { + host = ins->host.name; + } + else { + if (!ctx->region ) { + flb_errno(); + flb_plg_error(ctx->ins, "Region is required"); + return -1; + } + host = flb_sds_create_size(512); + flb_sds_snprintf(&host, flb_sds_alloc(host), "loganalytics.%s.oci.oraclecloud.com", ctx->region); + } + + io_flags = FLB_IO_TCP; + default_port = 80; + +#ifdef FLB_HAVE_TLS + if (ins->use_tls == FLB_TRUE) { + io_flags = FLB_IO_TLS; + default_port = 443; + } +#endif + + if (ins->host.ipv6 == FLB_TRUE) { + io_flags |= FLB_IO_IPV6; + } + + flb_output_net_default(host, default_port, ins); + flb_sds_destroy(host); + + if (ctx->proxy) { + ret = flb_utils_url_split(tmp, &protocol, &p_host, &p_port, &p_uri); + if (ret == -1) { + flb_plg_error(ctx->ins, "could not parse proxy parameter: '%s'", tmp); + return -1; + } + + ctx->proxy_host = p_host; + ctx->proxy_port = atoi(p_port); + flb_free(protocol); + flb_free(p_port); + flb_free(p_uri); + flb_free(p_host); + } + + if (ctx->proxy) { + upstream = flb_upstream_create(config, ctx->proxy_host, ctx->proxy_port, + io_flags, ins->tls); + } + else { + /* Prepare an upstream handler */ + upstream = flb_upstream_create(config, ins->host.name, ins->host.port, + io_flags, ins->tls); + } + + if (!upstream) { + flb_plg_error(ctx->ins, "cannot create Upstream context"); + return -1; + } + ctx->u = upstream; + + /* Set instance flags into upstream */ + flb_output_upstream_set(ctx->u, ins); + + return 0; +} + struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, struct flb_config *config) { struct flb_oci_logan *ctx; @@ -987,20 +1069,6 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, } } - if (ins->host.name) { - host = ins->host.name; - } - else { - if (!ctx->region) { - flb_errno(); - flb_plg_error(ctx->ins, "Region is required"); - flb_oci_logan_conf_destroy(ctx); - return NULL; - } - host = flb_sds_create_size(512); - flb_sds_snprintf(&host, flb_sds_alloc(host), "loganalytics.%s.oci.oraclecloud.com", ctx->region); - } - if (!ctx->uri) { if (!ctx->namespace) { flb_errno(); @@ -1028,61 +1096,16 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, "%s/%s/%s", ctx->tenancy, ctx->user, ctx->key_fingerprint); } - - /* Check if SSL/TLS is enabled */ - io_flags = FLB_IO_TCP; - default_port = 80; - -#ifdef FLB_HAVE_TLS - if (ins->use_tls == FLB_TRUE) { - io_flags = FLB_IO_TLS; - default_port = 443; - } -#endif - - if (ins->host.ipv6 == FLB_TRUE) { - io_flags |= FLB_IO_IPV6; - } - - flb_output_net_default(host, default_port, ins); - flb_sds_destroy(host); - - if (ctx->proxy) { - ret = flb_utils_url_split(tmp, &protocol, &p_host, &p_port, &p_uri); - if (ret == -1) { - flb_plg_error(ctx->ins, "could not parse proxy parameter: '%s'", tmp); + if (strcasecmp(ctx->auth_type, USER_PRINCIPAL) == 0 || + strcasecmp(ctx->auth_type, WORKLOAD_IDENTITY) == 0) { + ret = set_upstream_ctx(ctx, ins, config); + if (ret != 0) { + flb_plg_error(ctx->ins, "cannot create Upstream context"); flb_oci_logan_conf_destroy(ctx); return NULL; } - - ctx->proxy_host = p_host; - ctx->proxy_port = atoi(p_port); - flb_free(protocol); - flb_free(p_port); - flb_free(p_uri); - flb_free(p_host); } - if (ctx->proxy) { - upstream = flb_upstream_create(config, ctx->proxy_host, ctx->proxy_port, - io_flags, ins->tls); - } - else { - /* Prepare an upstream handler */ - upstream = flb_upstream_create(config, ins->host.name, ins->host.port, - io_flags, ins->tls); - } - - if (!upstream) { - flb_plg_error(ctx->ins, "cannot create Upstream context"); - flb_oci_logan_conf_destroy(ctx); - return NULL; - } - ctx->u = upstream; - - /* Set instance flags into upstream */ - flb_output_upstream_set(ctx->u, ins); - return ctx; } diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.h b/plugins/out_oracle_log_analytics/oci_logan_conf.h index 9e13f521c0d..7a8f1ee0ce9 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.h +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.h @@ -34,5 +34,8 @@ int refresh_security_token(struct flb_oci_logan *ctx, struct flb_config *config); int refresh_oke_workload_security_token(struct flb_oci_logan *ctx, struct flb_config *config); +int set_upstream_ctx(struct flb_oci_logan *ctx, + struct flb_output_instance *ins, + struct flb_config *config); #endif From fcc0ddcb68fa99c42f24aaa2aba425cda043b65d Mon Sep 17 00:00:00 2001 From: adiforluls Date: Tue, 21 Nov 2023 11:17:50 +0530 Subject: [PATCH 05/10] move authentication code to a common place Signed-off-by: adiforluls --- include/fluent-bit/oracle/flb_oracle_client.h | 170 ++ plugins/out_oracle_log_analytics/oci_client.c | 707 ------- plugins/out_oracle_log_analytics/oci_client.h | 100 - plugins/out_oracle_log_analytics/oci_logan.c | 200 +- .../out_oracle_log_analytics/oci_logan_conf.c | 800 +------- .../out_oracle_log_analytics/oci_logan_conf.h | 4 - src/CMakeLists.txt | 1 + src/oracle/flb_oracle_client.c | 1664 +++++++++++++++++ 8 files changed, 1853 insertions(+), 1793 deletions(-) create mode 100644 include/fluent-bit/oracle/flb_oracle_client.h delete mode 100644 plugins/out_oracle_log_analytics/oci_client.c delete mode 100644 plugins/out_oracle_log_analytics/oci_client.h create mode 100644 src/oracle/flb_oracle_client.c diff --git a/include/fluent-bit/oracle/flb_oracle_client.h b/include/fluent-bit/oracle/flb_oracle_client.h new file mode 100644 index 00000000000..5ee9bc7f4e8 --- /dev/null +++ b/include/fluent-bit/oracle/flb_oracle_client.h @@ -0,0 +1,170 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 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. + */ + + +#ifndef FLUENT_BIT_INCLUDE_FLUENT_BIT_ORACLE_FLB_ORACLE_CLIENT_H_ +#define FLUENT_BIT_INCLUDE_FLUENT_BIT_ORACLE_FLB_ORACLE_CLIENT_H_ + +#define RSA_EXP 65537 +#define FLB_OCI_TOKEN "token" + +#define OCI_FEDERATION_REQUEST_PAYLOAD "{\"certificate\":\"%s\",\"publicKey\":\"%s\", \"intermediateCertificates\":[\"%s\"]}" +#define OCI_OKE_PROXYMUX_PAYLOAD "{\"podKey\":\"%s\"}" + +/* Http Header */ +#define FLB_OCI_HEADER_REQUEST_TARGET "(request-target)" +#define FLB_OCI_HEADER_USER_AGENT "User-Agent" +#define FLB_OCI_HEADER_USER_AGENT_VAL "Fluent-Bit" +#define FLB_OCI_HEADER_CONTENT_TYPE "content-type" +#define FLB_OCI_HEADER_CONTENT_TYPE_JSON "application/json" +#define FLB_OCI_HEADER_CONTENT_TYPE_OCTET_STREAM "application/octet-stream" +#define FLB_OCI_HEADER_X_CONTENT_SHA256 "x-content-sha256" +#define FLB_OCI_HEADER_CONTENT_LENGTH "content-length" +#define FLB_OCI_HEADER_HOST "host" +#define FLB_OCI_HEADER_DATE "date" +#define FLB_OCI_HEADER_AUTH "Authorization" +#define FLB_OCI_PAYLOAD_TYPE "payloadType" + +/* For OCI signing */ +#define FLB_OCI_PARAM_TENANCY "tenancy" +#define FLB_OCI_PARAM_USER "user" +#define FLB_OCI_PARAM_KEY_FINGERPRINT "fingerprint" +#define FLB_OCI_PARAM_KEY_FILE "key_file" +#define FLB_OCI_PARAM_REGION "region" +#define FLB_OCI_PARAM_KEY_FILE_PASSPHRASE "key_file_passphrase" + +#define FLB_OCI_SIGN_SIGNATURE_VERSION "Signature version=\"1\"" +#define FLB_OCI_SIGN_KEYID "keyId" +#define FLB_OCI_SIGN_ALGORITHM "algorithm=\"rsa-sha256\"" + +#define FLB_OCI_SIGN_HEADERS "headers=\"" \ + FLB_OCI_HEADER_REQUEST_TARGET " " \ + FLB_OCI_HEADER_HOST " " \ + FLB_OCI_HEADER_DATE " " \ + FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ + FLB_OCI_HEADER_CONTENT_TYPE " " \ + FLB_OCI_HEADER_CONTENT_LENGTH "\"" + +#define FLB_OCI_SIGN_SIGNATURE "signature" +#define METADATA_HOST_BASE "169.254.169.254" +#define GET_REGION_URL "/opc/v2/instance/region" +#define GET_REGION_INFO_URL "/opc/v2/instance/regionInfo/" +#define LEAF_CERTIFICATE_URL "/opc/v2/identity/cert.pem" +#define LEAF_CERTIFICATE_PRIVATE_KEY_URL "/opc/v2/identity/key.pem" +#define INTERMEDIATE_CERTIFICATE_URL "/opc/v2/identity/intermediate.pem" + +#include +#include +#include + +struct federation_client { + struct flb_upstream *u; + flb_sds_t region; + flb_sds_t tenancy_id; + struct cert_retriever *leaf_cert_ret; + struct cert_retriever *intermediate_cert_ret; + // session key supplier + flb_sds_t private_key; + flb_sds_t public_key; + flb_sds_t key_id; + flb_sds_t security_token; + time_t expire; + pthread_mutex_t lock; +}; + +struct cert_retriever { + struct flb_upstream *u; + flb_sds_t cert_pem; + X509 *cert; + flb_sds_t private_key_pem; +}; + +int create_pk_context(flb_sds_t filepath, + const char *key_passphrase, + struct flb_output_instance *ins, + flb_sds_t *p_key); + +int load_oci_credentials(struct flb_output_instance *ins, + flb_sds_t config_file_location, + flb_sds_t profile_name, + flb_sds_t *user, flb_sds_t *tenancy, + flb_sds_t *key_file, flb_sds_t *key_fingerprint, + flb_sds_t *region); +flb_sds_t create_authorization_header_content(flb_sds_t key_id, + flb_sds_t signature); +flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, + flb_sds_t signing_string, + struct flb_output_instance *ins); +flb_sds_t get_date(void); +flb_sds_t add_header_and_signing(struct flb_http_client *c, + flb_sds_t signing_str, const char *header, int headersize, + const char *val, int val_size); +int build_headers(struct flb_http_client *c, + flb_sds_t private_key, + flb_sds_t key_id, flb_sds_t json, + flb_sds_t uri, + struct flb_output_instance *ins, + char *content_type); +int build_federation_client_headers(struct flb_http_client *c, + flb_sds_t private_key, + flb_sds_t key_id, flb_sds_t json, + flb_sds_t uri, + struct flb_output_instance *ins); +flb_sds_t refresh_cert(struct flb_upstream *u, flb_sds_t cert_url, + struct flb_output_instance *ins); +flb_sds_t get_tenancy_id_from_certificate(X509 *cert); +char* sanitize_certificate_string(flb_sds_t cert_pem); +void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len); +flb_sds_t fingerprint(X509 *cert); +int session_key_supplier(flb_sds_t *priv_key, + flb_sds_t *pub_key, + struct flb_output_instance *ins); +X509 *get_cert_from_string(flb_sds_t cert_pem); +flb_sds_t get_region(struct flb_upstream *u, flb_sds_t region_url, + struct flb_hash_table *ht); +flb_sds_t parse_token(char *response, + size_t response_len); +flb_sds_t add_header_and_signing(struct flb_http_client *c, + flb_sds_t signing_str, + const char *header, + int headersize, + const char *val, int val_size); +flb_sds_t get_date(void); +const char* get_token_exp(flb_sds_t token_string, + time_t *exp, + struct flb_output_instance *ins); +flb_sds_t create_fed_authorization_header_content(flb_sds_t signature, + flb_sds_t key_id); +void build_region_table(struct flb_hash_table **region_table); +int refresh_security_token(struct federation_client *fed_client, + struct flb_config *config, + struct flb_output_instance *ins, + struct flb_upstream *fed_u, + struct flb_upstream *cert_u, + struct flb_hash_table *region_table); +int refresh_oke_workload_security_token(struct federation_client *fed_client, + struct flb_config *config, + struct flb_output_instance *ins, + struct flb_upstream *fed_u, + flb_sds_t oke_sa_ca_file, + flb_sds_t oke_sa_token_file, + flb_sds_t *key_id); + +#endif //FLUENT_BIT_INCLUDE_FLUENT_BIT_ORACLE_FLB_ORACLE_CLIENT_H_ + diff --git a/plugins/out_oracle_log_analytics/oci_client.c b/plugins/out_oracle_log_analytics/oci_client.c deleted file mode 100644 index 4dcaed5d9bb..00000000000 --- a/plugins/out_oracle_log_analytics/oci_client.c +++ /dev/null @@ -1,707 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -/* Fluent Bit - * ========== - * Copyright (C) 2015-2023 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 "oci_client.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, - flb_sds_t signing_string) -{ - int len = 0, ret; - size_t outlen; - flb_sds_t signature; - unsigned char sha256_buf[32] = { 0 }; - unsigned char sig[256] = { 0 }; - size_t sig_len = sizeof(sig); - - ret = flb_hash_simple(FLB_HASH_SHA256, - (unsigned char*) signing_string, - flb_sds_len(signing_string), - sha256_buf, sizeof(sha256_buf)); - - if(ret != FLB_CRYPTO_SUCCESS) { - // flb_plg_error(ctx->ins, "error generating hash buffer"); - return NULL; - } - - ret = flb_crypto_sign_simple(FLB_CRYPTO_PRIVATE_KEY, - FLB_CRYPTO_PADDING_PKCS1, - FLB_HASH_SHA256, - (unsigned char *) private_key, - flb_sds_len(private_key), - sha256_buf, sizeof(sha256_buf), - sig, &sig_len); - - - if (ret != FLB_CRYPTO_SUCCESS) { - // flb_plg_error(ctx->ins, "error signing SHA256"); - return NULL; - } - - signature = flb_sds_create_size(512); - if (!signature) { - flb_errno(); - return NULL; - } - - /* base 64 encode */ - len = flb_sds_alloc(signature) - 1; - flb_base64_encode((unsigned char*) signature, len, &outlen, sig, - sizeof(sig)); - signature[outlen] = '\0'; - flb_sds_len_set(signature, outlen); - - return signature; -} - -flb_sds_t get_date(void) -{ - - flb_sds_t rfc1123date; - time_t t; - size_t size; - struct tm tm = { 0 }; - - /* Format Date */ - rfc1123date = flb_sds_create_size(32); - if (!rfc1123date) { - flb_errno(); - return NULL; - } - - t = time(NULL); - if (!gmtime_r(&t, &tm)) { - flb_errno(); - flb_sds_destroy(rfc1123date); - return NULL; - } - size = strftime(rfc1123date, flb_sds_alloc(rfc1123date) - 1, - "%a, %d %b %Y %H:%M:%S GMT", &tm); - if (size <= 0) { - flb_errno(); - flb_sds_destroy(rfc1123date); - return NULL; - } - flb_sds_len_set(rfc1123date, size); - return rfc1123date; -} - -flb_sds_t add_header_and_signing(struct flb_http_client *c, - flb_sds_t signing_str, - const char *header, - int headersize, - const char *val, int val_size) -{ - if (!signing_str) { - return NULL; - } - - flb_http_add_header(c, header, headersize, val, val_size); - - signing_str = flb_sds_cat(signing_str, "\n", 1); - signing_str = flb_sds_cat(signing_str, header, headersize); - signing_str = flb_sds_cat(signing_str, ": ", 2); - signing_str = flb_sds_cat(signing_str, val, val_size); - - return signing_str; -} - -/* - * Authorization: Signature version="1",keyId="//", - * algorithm="rsa-sha256",headers="(request-target) date x-content-sha256 content-type content-length", - * signature="signature" - */ -flb_sds_t create_authorization_header_content(flb_sds_t signature, - flb_sds_t key_id) -{ - flb_sds_t content; - - content = flb_sds_create_size(1024*10); - content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE_VERSION, - sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_SIGN_KEYID, - sizeof(FLB_OCI_SIGN_KEYID) - 1); - content = flb_sds_cat(content, "=\"", 2); - content = flb_sds_cat(content, key_id, flb_sds_len(key_id)); - content = flb_sds_cat(content, "\",", 2); - content = flb_sds_cat(content, FLB_OCI_SIGN_ALGORITHM, - sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_SIGN_HEADERS, - sizeof(FLB_OCI_SIGN_HEADERS) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE, - sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); - content = flb_sds_cat(content, "=\"", 2); - content = flb_sds_cat(content, signature, flb_sds_len(signature)); - content = flb_sds_cat(content, "\"", 1); - - return content; -} - -flb_sds_t create_fed_authorization_header_content(flb_sds_t signature, - flb_sds_t key_id) -{ - flb_sds_t content; - - content = flb_sds_create_size(512); - content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE_VERSION, - sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_SIGN_KEYID, - sizeof(FLB_OCI_SIGN_KEYID) - 1); - content = flb_sds_cat(content, "=\"", 2); - content = flb_sds_cat(content, key_id, flb_sds_len(key_id)); - content = flb_sds_cat(content, "\",", 2); - content = flb_sds_cat(content, FLB_OCI_SIGN_ALGORITHM, - sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_FED_SIGN_HEADERS, - sizeof(FLB_OCI_FED_SIGN_HEADERS) - 1); - content = flb_sds_cat(content, ",", 1); - content = flb_sds_cat(content, FLB_OCI_SIGN_SIGNATURE, - sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); - content = flb_sds_cat(content, "=\"", 2); - content = flb_sds_cat(content, signature, flb_sds_len(signature)); - content = flb_sds_cat(content, "\"", 1); - - return content; -} - -flb_sds_t refresh_cert(struct flb_upstream *u, - flb_sds_t cert_url, - struct flb_output_instance *ins) -{ - flb_sds_t cert = NULL; - struct flb_connection *u_conn; - struct flb_http_client *c; - int ret = 0; - size_t b_sent; - u_conn = flb_upstream_conn_get(u); - if (!u_conn) { - flb_errno(); - return NULL; - } - - c = flb_http_client(u_conn, FLB_HTTP_GET, cert_url, NULL, 0, - NULL, 0, NULL, 0); - - if (!c) { - flb_errno(); - flb_upstream_conn_release(u_conn); - return NULL; - } - - flb_http_strip_port_from_host(c); - flb_http_buffer_size(c, 0); - flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); - flb_http_add_header(c, "Accept", 6, "*/*", 3); - flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); - - ret = flb_http_do(c, &b_sent); - - if (ret != 0) { - flb_errno(); - flb_plg_error(ins, "http do error"); - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return NULL; - } - - if (c->resp.status != 200 && c->resp.status != 204 && c->resp.status != 201) { - flb_errno(); - flb_plg_info(ins, "request header = %s", c->header_buf); - flb_plg_error(ins, "request was not successful with status = %d payload = %s url = %s", - c->resp.status, c->resp.payload, cert_url); - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return NULL; - } - - cert = flb_sds_create_len(c->resp.payload, c->resp.payload_size); - - if (!cert) { - flb_errno(); - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return NULL; - } - - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return cert; -} - -// finish this func -flb_sds_t get_tenancy_id_from_certificate(X509 *cert) -{ - flb_sds_t t_id = NULL; - int i; - const unsigned char *str; - char* x; - - X509_NAME *subj = X509_get_subject_name(cert); - - for (i = 0; i < X509_NAME_entry_count(subj); i++) { - X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, i); - ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); - str = ASN1_STRING_get0_data(d); - x = strstr((const char *) str, "opc-tenant:"); - if (x) { - break; - } - } - - t_id = flb_sds_create((const char*) str + 11); - - return t_id; -} - -char* sanitize_certificate_string(flb_sds_t cert_pem) -{ - // i2d_X509() - char sanitized[strlen(cert_pem) + 1]; - strcpy(sanitized, cert_pem); - char c_start[] = "-----BEGIN CERTIFICATE-----"; - size_t c_st_len = strlen(c_start); - char c_end[] = "-----END CERTIFICATE-----"; - char k_start[] = "-----BEGIN PUBLIC KEY-----"; - size_t k_st_len = strlen(k_start); - char k_end[] = "-----END PUBLIC KEY-----"; - char *p = NULL, *q = NULL, *ans, *tmp, *a; - - p = strstr(sanitized, c_start); - q = strstr(sanitized, c_end); - if (p && q) { - *q = '\0'; - tmp = p + c_st_len + 1; - } - else { - p = strstr(sanitized, k_start); - q = strstr(sanitized, k_end); - *q = '\0'; - tmp = p + k_st_len; - } - ans = flb_malloc(strlen(sanitized) + sizeof(char)); - a = ans; - while(*tmp != '\0') - { - if(*tmp != '\t' && *tmp != '\n') { - *a++ = *tmp++; - } - else { - ++tmp; - } - } - *a = '\0'; - - return ans; - -} - -void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len) -{ - char *l; - size_t i; - for(i=0; i < len-1; i++) { - l = (char*) (3*i + ((intptr_t) writebuf)); - sprintf(l, "%02x:", readbuf[i]); - } - - l = (char*) (3*(len - 1) + ((intptr_t) writebuf)); - sprintf(l, "%02x", readbuf[len - 1]); -} - -flb_sds_t fingerprint(X509 *cert) -{ - // i2d_X509() - flb_sds_t fingerprint = NULL; - const EVP_MD *digest; - unsigned char md[SHA_DIGEST_LENGTH]; - char buf[3*SHA_DIGEST_LENGTH+1]; - unsigned int n; - - digest = EVP_get_digestbyname("sha1"); - X509_digest(cert, digest, md, &n); - - colon_separated_fingerprint(md, (void *) buf, (size_t) SHA_DIGEST_LENGTH); - - fingerprint = flb_sds_create_len(buf, 3*SHA_DIGEST_LENGTH); - return fingerprint; -} - -int session_key_supplier(flb_sds_t *priv_key, - flb_sds_t *pub_key, - struct flb_output_instance *ins) -{ - // Key generation - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); - EVP_PKEY* key = NULL; - BIO *pri, *pub; - int priKeyLen; - int pubKeyLen; - char* priKeyStr; - char* pubKeyStr; - int ret; - BIGNUM *bne = NULL; - - bne = BN_new(); - ret = BN_set_word(bne, RSA_EXP); - if (ret != 1) { - return -1; - } - EVP_PKEY_keygen_init(ctx); - EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bne); - EVP_PKEY_keygen(ctx, &key); - EVP_PKEY_CTX_free(ctx); - - // Serialize to string - pri = BIO_new(BIO_s_mem()); - pub = BIO_new(BIO_s_mem()); - PEM_write_bio_PrivateKey_traditional(pri, key, NULL, NULL, 0, 0, NULL); - PEM_write_bio_PUBKEY(pub, key); - - priKeyLen = BIO_pending(pri); - pubKeyLen = BIO_pending(pub); - priKeyStr = flb_malloc(priKeyLen); - pubKeyStr = flb_malloc(pubKeyLen); - BIO_read(pri, priKeyStr, priKeyLen); - BIO_read(pub, pubKeyStr, pubKeyLen); - priKeyStr[priKeyLen] = '\0'; - pubKeyStr[pubKeyLen] = '\0'; - // flb_plg_info(ins, "private_key = %s", priKeyStr); - // flb_plg_info(ins, "pub_key = %s", pubKeyStr); - - *priv_key = flb_sds_create_len((const char *) priKeyStr, priKeyLen); - *pub_key = flb_sds_create_len((const char *)pubKeyStr, pubKeyLen); - - BIO_free(pri); - BIO_free(pub); - flb_free(priKeyStr); - flb_free(pubKeyStr); - BN_free(bne); - - return 0; -} - -X509 *get_cert_from_string(flb_sds_t cert_pem) -{ - X509 *cert; - BIO* certBio = BIO_new(BIO_s_mem()); - BIO_write(certBio, cert_pem, (int) flb_sds_len(cert_pem)); - cert = PEM_read_bio_X509(certBio, NULL, NULL, NULL); - - BIO_free(certBio); - return cert; -} - -flb_sds_t get_region(struct flb_upstream *u, - flb_sds_t region_url, - struct flb_hash_table *ht) -{ - flb_sds_t region; - char* temp_region = NULL; - struct flb_connection *u_conn; - struct flb_http_client *c; - size_t b_sent, temp_sz; - int ret; - - // TODO: construct region uri - u_conn = flb_upstream_conn_get(u); - if (!u_conn) { - flb_errno(); - return NULL; - } - - c = flb_http_client(u_conn, FLB_HTTP_GET, region_url, - NULL, 0, NULL, 0, NULL, 0); - if (!c) { - flb_errno(); - return NULL; - } - - flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); - flb_http_add_header(c, "Accept", 6, "*/*", 3); - flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); - - ret = flb_http_do(c, &b_sent); - - if (ret != 0) { - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return NULL; - } - - if (c->resp.status != 200 && c->resp.status != 201 && - c->resp.status != 204) { - flb_upstream_conn_release(u_conn); - flb_http_client_destroy(c); - return NULL; - } - - ret = flb_hash_table_get(ht, mk_string_tolower(c->resp.payload), - (int)c->resp.payload_size, - (void *)&temp_region, - &temp_sz); - if (ret < 0) { - temp_region = c->resp.payload; - temp_sz = c->resp.payload_size; - } - - region = flb_sds_create_len(temp_region, - (int) temp_sz); - - return region; -} - -flb_sds_t parse_token(char *response, - size_t response_len) -{ - int tok_size = 32, ret, i; - jsmn_parser parser; - jsmntok_t *t; - jsmntok_t *tokens; - char *key; - char *val; - int key_len; - int val_len; - flb_sds_t token = NULL; - - jsmn_init(&parser); - - tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); - if (!tokens) { - flb_errno(); - return NULL; - } - - ret = jsmn_parse(&parser, response, response_len, tokens, tok_size); - - if (ret<=0) { - flb_free(tokens); - return NULL; - } - tok_size = ret; - - /* Parse JSON tokens */ - for (i = 0; i < tok_size; i++) { - t = &tokens[i]; - - if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { - break; - } - - if (t->type != JSMN_STRING) { - continue; - } - - key = response + t->start; - key_len = (t->end - t->start); - - i++; - t = &tokens[i]; - val = response + t->start; - val_len = (t->end - t->start); - - if (val_len < 1) { - continue; - } - - if ((key_len == sizeof(FLB_OCI_TOKEN) - 1) - && strncasecmp(key, FLB_OCI_TOKEN, - sizeof(FLB_OCI_TOKEN) - 1) == 0) { - // code - token = flb_sds_create_len(val, val_len); - if (!token) { - flb_free(tokens); - return NULL; - } - break; - } - } - - flb_free(tokens); - return token; -} - -static const char *jwt_decode_payload(const char *src, - char **bufplainp) { - char *converted_src; - char *payload = NULL; - - const char *errstr = NULL; - - int i, padding, len; - - int payload_len; - int nbytesdecoded; - - int payloads_start = 0; - int payloads_end = 0; - - len = (int)strlen(src); - converted_src = flb_malloc(len + 4); - - for (i = 0; i < len; i++) { - switch (src[i]) { - case '-': - converted_src[i] = '+'; - break; - - case '_': - converted_src[i] = '/'; - break; - - case '.': - if (payloads_start == 0) - payloads_start = i + 1; - else { - if (payloads_end > 0) { - errstr = - "The token is invalid with more " - "than 2 delimiters"; - goto done; - } - payloads_end = i; - } - /* FALLTHRU */ - - default: - converted_src[i] = src[i]; - } - } - - if (payloads_start == 0 || payloads_end == 0) { - errstr = "The token is invalid with less than 2 delimiters"; - goto done; - } - - payload_len = payloads_end - payloads_start; - payload = flb_malloc(payload_len + 4); - strncpy(payload, (converted_src + payloads_start), payload_len); - - padding = 4 - (payload_len % 4); - if (padding < 4) { - while (padding--) - payload[payload_len++] = '='; - } - - nbytesdecoded = ((payload_len + 3) / 4) * 3; - *bufplainp = flb_malloc(nbytesdecoded + 1); - - if (EVP_DecodeBlock((uint8_t *)(*bufplainp), (uint8_t *)payload, - (int)payload_len) == -1) { - errstr = "Failed to decode base64 payload"; - } - - done: - flb_free(payload); - flb_free(converted_src); - return errstr; -} - -const char* get_token_exp(flb_sds_t token_string, - time_t *exp, - struct flb_output_instance *ins) -{ - char *payload = NULL; - const char* err_str = NULL; - - err_str = jwt_decode_payload(token_string, &payload); - // flb_plg_info(ins, "jwt payload = %s", payload); - - if (err_str != NULL) { - return err_str; - } - - int tok_size = 256, ret, i; - jsmn_parser parser; - jsmntok_t *t; - jsmntok_t *tokens; - char *key; - char *val; - int key_len; - int val_len; - - jsmn_init(&parser); - - tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); - if (!tokens) { - flb_errno(); - return NULL; - } - - ret = jsmn_parse(&parser, payload, strlen(payload), tokens, tok_size); - - if (ret<=0) { - flb_free(tokens); - return NULL; - } - tok_size = ret; - - /* Parse JSON tokens */ - for (i = 0; i < tok_size; i++) { - t = &tokens[i]; - - if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { - break; - } - - if (t->type != JSMN_STRING) { - continue; - } - - key = payload + t->start; - key_len = (t->end - t->start); - - i++; - t = &tokens[i]; - val = payload + t->start; - val_len = (t->end - t->start); - - if (val_len < 1) { - continue; - } - - // flb_plg_info(ins, "sectoken %s: %s", key, val); - if ((key_len == 3) - && strncasecmp(key, "exp", - 3) == 0) { - // code - flb_plg_info(ins, "fetched exp time = %s", val); - *exp = atol(val); - break; - } - } - - flb_free(tokens); - return err_str; -} diff --git a/plugins/out_oracle_log_analytics/oci_client.h b/plugins/out_oracle_log_analytics/oci_client.h deleted file mode 100644 index 4aa78cd5b72..00000000000 --- a/plugins/out_oracle_log_analytics/oci_client.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -/* Fluent Bit - * ========== - * Copyright (C) 2015-2023 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. - */ - - - -#ifndef FLUENT_BIT_OUT_OCI_LOGAN_OCI_CLIENT_H -#define FLUENT_BIT_OUT_OCI_LOGAN_OCI_CLIENT_H - -#define FLB_OCI_TOKEN "token" -#define RSA_EXP 65537 - -#define FLB_OCI_HEADER_REQUEST_TARGET "(request-target)" -#define FLB_OCI_HEADER_USER_AGENT "User-Agent" -#define FLB_OCI_HEADER_USER_AGENT_VAL "Fluent-Bit" -#define FLB_OCI_HEADER_CONTENT_TYPE "content-type" -#define FLB_OCI_HEADER_CONTENT_TYPE_VAL "application/octet-stream" -#define FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL "application/json" -#define FLB_OCI_HEADER_X_CONTENT_SHA256 "x-content-sha256" -#define FLB_OCI_HEADER_CONTENT_LENGTH "content-length" -#define FLB_OCI_HEADER_HOST "host" -#define FLB_OCI_HEADER_DATE "date" -#define FLB_OCI_HEADER_AUTH "Authorization" -#define FLB_OCI_PAYLOAD_TYPE "payloadType" - -#define FLB_OCI_SIGN_SIGNATURE_VERSION "Signature version=\"1\"" -#define FLB_OCI_SIGN_KEYID "keyId" -#define FLB_OCI_SIGN_ALGORITHM "algorithm=\"rsa-sha256\"" - -#define FLB_OCI_SIGN_HEADERS "headers=\"" \ - FLB_OCI_HEADER_REQUEST_TARGET " " \ - FLB_OCI_HEADER_HOST " " \ - FLB_OCI_HEADER_DATE " " \ - FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ - FLB_OCI_HEADER_CONTENT_TYPE " " \ - FLB_OCI_HEADER_CONTENT_LENGTH "\"" - -#define FLB_OCI_SIGN_SIGNATURE "signature" -#define FLB_OCI_FED_SIGN_HEADERS "headers=\"" \ - FLB_OCI_HEADER_REQUEST_TARGET " " \ - FLB_OCI_HEADER_DATE " " \ - FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ - FLB_OCI_HEADER_CONTENT_TYPE " " \ - FLB_OCI_HEADER_CONTENT_LENGTH "\"" - - -#endif //FLUENT_BIT_PLUGINS_OUT_OCI_LOGAN_OCI_CLIENT_H_ - -#include -#include -#include -#include -#include -#include -#include - -flb_sds_t refresh_cert(struct flb_upstream *u, flb_sds_t cert_url, - struct flb_output_instance *ins); -flb_sds_t get_tenancy_id_from_certificate(X509 *cert); -char* sanitize_certificate_string(flb_sds_t cert_pem); -void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len); -flb_sds_t fingerprint(X509 *cert); -int session_key_supplier(flb_sds_t *priv_key, - flb_sds_t *pub_key, - struct flb_output_instance *ins); -X509 *get_cert_from_string(flb_sds_t cert_pem); -flb_sds_t get_region(struct flb_upstream *u, flb_sds_t region_url, - struct flb_hash_table *ht); -flb_sds_t parse_token(char *response, - size_t response_len); -flb_sds_t add_header_and_signing(struct flb_http_client *c, - flb_sds_t signing_str, - const char *header, - int headersize, - const char *val, int val_size); -flb_sds_t get_date(void); -flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, - flb_sds_t signing_string); -flb_sds_t create_authorization_header_content(flb_sds_t signature, - flb_sds_t key_id); -const char* get_token_exp(flb_sds_t token_string, - time_t *exp, - struct flb_output_instance *ins); -flb_sds_t create_fed_authorization_header_content(flb_sds_t signature, - flb_sds_t key_id); diff --git a/plugins/out_oracle_log_analytics/oci_logan.c b/plugins/out_oracle_log_analytics/oci_logan.c index 68bd75985b8..cea89c1aada 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.c +++ b/plugins/out_oracle_log_analytics/oci_logan.c @@ -37,6 +37,7 @@ #include "oci_logan_conf.h" #include "oci_logan.h" +#include static int check_config_from_record(msgpack_object key, @@ -54,192 +55,6 @@ static int check_config_from_record(msgpack_object key, return memcmp(key.via.str.ptr, name, len) == 0; } -static int build_headers(struct flb_http_client *c, struct flb_oci_logan *ctx, - flb_sds_t json, flb_sds_t hostname, int port, flb_sds_t uri) -{ - int ret = -1; - flb_sds_t tmp_sds = NULL; - flb_sds_t tmp_sds_1 = NULL; - flb_sds_t signing_str = NULL; - flb_sds_t rfc1123date = NULL; - flb_sds_t encoded_uri = NULL; - flb_sds_t signature = NULL; - flb_sds_t auth_header_str = NULL; - - flb_sds_t tmp_ref = NULL; - - size_t tmp_len = 0; - - unsigned char sha256_buf[32] = { 0 }; - - tmp_sds = flb_sds_create_size(512); - if (!tmp_sds) { - flb_errno(); - goto error_label; - } - - signing_str = flb_sds_create_size(1024); - if (!signing_str) { - flb_errno(); - goto error_label; - } - - // Add (requeset-target) to signing string - encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); - if (!encoded_uri) { - flb_errno(); - goto error_label; - } - signing_str = flb_sds_cat(signing_str, FLB_OCI_HEADER_REQUEST_TARGET, - sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); - signing_str = flb_sds_cat(signing_str, ": post ", sizeof(": post ") - 1); - signing_str = flb_sds_cat(signing_str, encoded_uri, - flb_sds_len(encoded_uri)); - - // Add Host to Header - if (((c->flags & FLB_IO_TLS) && c->port == 443) - || (!(c->flags & FLB_IO_TLS) && c->port == 80)) { - // default port - tmp_ref = flb_sds_copy(tmp_sds, c->host, strlen(c->host)); - } - else { - tmp_ref = flb_sds_printf(&tmp_sds, "%s:%i", c->host, c->port); - } - if (!tmp_ref) { - flb_plg_error(ctx->ins, "cannot compose temporary host header"); - goto error_label; - } - tmp_sds = tmp_ref; - tmp_ref = NULL; - - signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_HOST, - sizeof(FLB_OCI_HEADER_HOST) - 1, - tmp_sds, flb_sds_len(tmp_sds)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add Date header - rfc1123date = get_date(); - if (!rfc1123date) { - flb_plg_error(ctx->ins, "cannot compose temporary date header"); - goto error_label; - } - signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_DATE, - sizeof(FLB_OCI_HEADER_DATE) - 1, rfc1123date, - flb_sds_len(rfc1123date)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - tmp_sds_1 = flb_sds_create_size(1024); - // Add x-content-sha256 Header - ret = flb_hash_simple(FLB_HASH_SHA256, - (unsigned char*) json, - flb_sds_len(json), - sha256_buf, sizeof(sha256_buf)); - - if (ret != FLB_CRYPTO_SUCCESS) { - flb_plg_error(ctx->ins, "error forming hash buffer for x-content-sha256 Header"); - goto error_label; - } - - flb_base64_encode((unsigned char*) tmp_sds_1, flb_sds_len(tmp_sds_1) - 1, - &tmp_len, sha256_buf, sizeof(sha256_buf)); - - tmp_sds_1[tmp_len] = '\0'; - flb_sds_len_set(tmp_sds_1, tmp_len); - - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_X_CONTENT_SHA256, - sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds_1, - flb_sds_len(tmp_sds_1)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add content-Type - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, - FLB_OCI_HEADER_CONTENT_TYPE_VAL, - sizeof(FLB_OCI_HEADER_CONTENT_TYPE_VAL) - 1); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add content-Length - tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", - (int) flb_sds_len(json)); - flb_sds_len_set(tmp_sds, tmp_len); - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_CONTENT_LENGTH, sizeof(FLB_OCI_HEADER_CONTENT_LENGTH) - 1, - tmp_sds, flb_sds_len(tmp_sds)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - flb_plg_info(ctx->ins, "signing str = %s", signing_str); - // Add Authorization header - signature = create_base64_sha256_signature(ctx->private_key, signing_str); - if (!signature) { - flb_plg_error(ctx->ins, "cannot compose signing signature"); - goto error_label; - } - - flb_plg_info(ctx->ins, "signature = %s", signature); - - auth_header_str = create_authorization_header_content( signature, ctx->key_id); - if (!auth_header_str) { - flb_plg_error(ctx->ins, "cannot compose authorization header"); - goto error_label; - } - - flb_plg_info(ctx->ins, "auth header str = %s", auth_header_str); - - flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, - auth_header_str, flb_sds_len(auth_header_str)); - - // User-Agent - flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, - sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, - FLB_OCI_HEADER_USER_AGENT_VAL, - sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); - - // Accept - flb_http_add_header(c, "Accept", 6, "*/*", 3); - - ret = 0; - - error_label: - if (tmp_sds) { - flb_sds_destroy(tmp_sds); - } - if (tmp_sds_1) { - flb_sds_destroy(tmp_sds_1); - } - if (signing_str) { - flb_sds_destroy(signing_str); - } - if (rfc1123date) { - flb_sds_destroy(rfc1123date); - } - if (encoded_uri) { - flb_sds_destroy(encoded_uri); - } - if (signature) { - flb_sds_destroy(signature); - } - if (auth_header_str) { - flb_sds_destroy(auth_header_str); - } - return ret; -} - static struct flb_oci_error_response* parse_response_error(struct flb_oci_logan *ctx, char *response, size_t response_len) { @@ -530,7 +345,7 @@ static int flush_to_endpoint(struct flb_oci_logan *ctx, flb_plg_debug(ctx->ins, "built client"); flb_http_buffer_size(c, FLB_HTTP_DATA_SIZE_MAX); - if (build_headers(c, ctx, payload, ctx->ins->host.name, ctx->ins->host.port, full_uri) < 0) { + if (build_headers(c, ctx->private_key, ctx->key_id, payload, full_uri, ctx->ins, FLB_OCI_HEADER_CONTENT_TYPE_OCTET_STREAM) < 0) { flb_plg_error(ctx->ins, "failed to build headers"); goto error_label; } @@ -1067,7 +882,10 @@ static void cb_oci_logan_flush(struct flb_event_chunk *event_chunk, flb_sds_t host = NULL; if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { - ret = refresh_security_token(ctx, config); + ret = refresh_security_token(ctx->fed_client, config, + ctx->ins, ctx->fed_u, + ctx->cert_u, + ctx->region_table); if (ret != 0) { flb_errno(); FLB_OUTPUT_RETURN(FLB_RETRY); @@ -1085,7 +903,11 @@ static void cb_oci_logan_flush(struct flb_event_chunk *event_chunk, flb_plg_debug(ctx->ins, "key_id = %s", ctx->key_id); } if (strcasecmp(ctx->auth_type, WORKLOAD_IDENTITY) == 0) { - ret = refresh_oke_workload_security_token(ctx, config); + ret = refresh_oke_workload_security_token(ctx->fed_client, config, + ctx->ins, ctx->fed_u, + ctx->oke_sa_ca_file, + ctx->oke_sa_token_file, + &ctx->key_id); if (ret != 0) { flb_errno(); flb_plg_error(ctx->ins, diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.c b/plugins/out_oracle_log_analytics/oci_logan_conf.c index 0feb656b168..2da03e8b98a 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.c +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.c @@ -35,798 +35,8 @@ #include "oci_logan.h" #include "oci_logan_conf.h" +#include -char* short_names[] = { - "yny\0", - "hyd\0", - "mel\0", - "bom\0", - "kix\0", - "icn\0", - "syd\0", - "nrt\0", - "yul\0", - "yyz\0", - "ams\0", - "fra\0", - "zrh\0", - "jed\0", - "dxb\0", - "gru\0", - "cwl\0", - "lhr\0", - "iad\0", - "phx\0", - "sjc\0", - "vcp\0", - "scl\0", - "mtz\0", - "mrs\0", - "sin\0", - "auh\0", - "lin\0", - "arn\0", - "jnb\0", - "cdg\0", - "qro\0", - "mad\0", - "ord\0", - "lfi\0", - "luf\0", - "ric\0", - "pia\0", - "tus\0", - "ltn\0", - "brs\0", - "nja\0", - "ukb\0", - "mct\0", - "wga\0", - "bgy\0", - "mxp\0", - "snn\0", - "dtm\0", - "dus\0", - "ork\0", - "vll\0", - "str\0", - "beg\0", - NULL -}; - -char *long_names[] = { - "ap-chuncheon-1\0", - "ap-hyderabad-1\0", - "ap-melbourne-1\0", - "ap-mumbai-1\0", - "ap-osaka-1\0", - "ap-seoul-1\0", - "ap-sydney-1\0", - "ap-tokyo-1\0", - "ca-montreal-1\0", - "ca-toronto-1\0", - "eu-amsterdam-1\0", - "eu-frankfurt-1\0", - "eu-zurich-1\0", - "me-jeddah-1\0", - "me-dubai-1\0", - "sa-saopaulo-1\0", - "uk-cardiff-1\0", - "uk-london-1\0", - "us-ashburn-1\0", - "us-phoenix-1\0", - "us-sanjose-1\0", - "sa-vinhedo-1\0", - "sa-santiago-1\0", - "il-jerusalem-1\0", - "eu-marseille-1\0", - "ap-singapore-1\0", - "me-abudhabi-1\0", - "eu-milan-1\0", - "eu-stockholm-1\0", - "af-johannesburg-1\0", - "eu-paris-1\0", - "mx-queretaro-1\0", - "eu-madrid-1\0", - "us-chicago-1\0", - "us-langley-1\0", - "us-luke-1\0", - "us-gov-ashburn-1\0", - "us-gov-chicago-1\0", - "us-gov-phoenix-1\0", - "uk-gov-london-1\0", - "uk-gov-cardiff-1\0", - "ap-chiyoda-1\0", - "ap-ibaraki-1\0", - "me-dcc-muscat-1\0", - "ap-dcc-canberra-1\0", - "eu-dcc-milan-1\0", - "eu-dcc-milan-2\0", - "eu-dcc-dublin-2\0", - "eu-dcc-rating-2\0", - "eu-dcc-rating-1\0", - "eu-dcc-dublin-1\0", - "eu-madrid-2\0", - "eu-frankfurt-2\0", - "eu-jovanovac-1\0", - NULL -}; - -static void build_region_table(struct flb_oci_logan *ctx) { - ctx->region_table = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE, 100, 0); - int i; - for(i = 0; short_names[i] != NULL; i++) { - flb_hash_table_add(ctx->region_table, - short_names[i], - strlen(short_names[i]), - long_names[i], - strlen(long_names[i])); - } - -} - -static int build_federation_client_headers(struct flb_oci_logan *ctx, - struct flb_http_client *c, - flb_sds_t json, - flb_sds_t uri) -{ - int ret = -1; - flb_sds_t tmp_sds = NULL; - flb_sds_t signing_str = NULL; - flb_sds_t rfc1123date = NULL; - flb_sds_t encoded_uri = NULL; - flb_sds_t signature = NULL; - flb_sds_t auth_header_str = NULL; - - size_t tmp_len = 0; - - unsigned char sha256_buf[32] = { 0 }; - - tmp_sds = flb_sds_create_size(512); - if (!tmp_sds) { - flb_errno(); - goto error_label; - } - - signing_str = flb_sds_create_size(1024); - if (!signing_str) { - flb_errno(); - goto error_label; - } - - // Add (requeset-target) to signing string - encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); - if (!encoded_uri) { - flb_errno(); - goto error_label; - } - signing_str = flb_sds_cat(signing_str, FLB_OCI_HEADER_REQUEST_TARGET, - sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); - signing_str = flb_sds_cat(signing_str, ": post ", sizeof(": post ") - 1); - signing_str = flb_sds_cat(signing_str, encoded_uri, - flb_sds_len(encoded_uri)); - - // Add Date header - rfc1123date = get_date(); - if (!rfc1123date) { - flb_plg_error(ctx->ins, "cannot compose temporary date header"); - goto error_label; - } - signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_DATE, - sizeof(FLB_OCI_HEADER_DATE) - 1, rfc1123date, - flb_sds_len(rfc1123date)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add x-content-sha256 Header - ret = flb_hash_simple(FLB_HASH_SHA256, - (unsigned char*) json, - flb_sds_len(json), - sha256_buf, sizeof(sha256_buf)); - - if (ret != FLB_CRYPTO_SUCCESS) { - flb_plg_error(ctx->ins, "error forming hash buffer for x-content-sha256 Header"); - goto error_label; - } - - flb_base64_encode((unsigned char*) tmp_sds, flb_sds_len(tmp_sds) - 1, - &tmp_len, sha256_buf, sizeof(sha256_buf)); - - tmp_sds[tmp_len] = '\0'; - flb_sds_len_set(tmp_sds, tmp_len); - - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_X_CONTENT_SHA256, - sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds, - flb_sds_len(tmp_sds)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add content-Type - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, - FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL, - sizeof(FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL) - 1); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add content-Length - tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", - (int) strlen(json)); - flb_sds_len_set(tmp_sds, tmp_len); - signing_str = add_header_and_signing(c, signing_str, - FLB_OCI_HEADER_CONTENT_LENGTH, sizeof(FLB_OCI_HEADER_CONTENT_LENGTH) - 1, - tmp_sds, flb_sds_len(tmp_sds)); - if (!signing_str) { - flb_plg_error(ctx->ins, "cannot compose signing string"); - goto error_label; - } - - // Add Authorization header - signature = create_base64_sha256_signature(ctx->fed_client->leaf_cert_ret->private_key_pem, - signing_str); - if (!signature) { - flb_plg_error(ctx->ins, "cannot compose signing signature"); - goto error_label; - } - - auth_header_str = create_fed_authorization_header_content(signature, ctx->fed_client->key_id); - if (!auth_header_str) { - flb_plg_error(ctx->ins, "cannot compose authorization header"); - goto error_label; - } - - flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, - auth_header_str, flb_sds_len(auth_header_str)); - - // User-Agent - flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, - sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, - FLB_OCI_HEADER_USER_AGENT_VAL, - sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); - - // Accept - flb_http_add_header(c, "Accept", 6, "*/*", 3); - - ret = 0; - - error_label: - if (tmp_sds) { - flb_sds_destroy(tmp_sds); - } - if (signing_str) { - flb_sds_destroy(signing_str); - } - if (rfc1123date) { - flb_sds_destroy(rfc1123date); - } - if (encoded_uri) { - flb_sds_destroy(encoded_uri); - } - if (signature) { - flb_sds_destroy(signature); - } - if (auth_header_str) { - flb_sds_destroy(auth_header_str); - } - return ret; - -} - -int refresh_security_token(struct flb_oci_logan *ctx, - struct flb_config *config) -{ - flb_sds_t region; - flb_sds_t host; - flb_sds_t fed_uri; - char* err; - struct flb_upstream *upstream; - struct flb_connection *u_conn; - struct flb_http_client *c; - struct flb_kv *kv; - struct mk_list *tmp; - struct mk_list *head; - char *s_leaf_cert, *s_inter_cert, *s_pub_key; - int ret = -1, sz; - time_t now; - size_t b_sent; - flb_sds_t json; - if (ctx->fed_client && ctx->fed_client->expire) { - now = time(NULL); - if (ctx->fed_client->expire > now) { - return 0; - } - } - if (!ctx->fed_client) { - ctx->fed_client = flb_calloc(1, sizeof(struct federation_client)); - } - if (!ctx->fed_client->leaf_cert_ret) { - ctx->fed_client->leaf_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); - } - if (!ctx->fed_client->intermediate_cert_ret) { - ctx->fed_client->intermediate_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); - } - - ctx->fed_client->leaf_cert_ret->cert_pem = refresh_cert(ctx->cert_u, - LEAF_CERTIFICATE_URL, - ctx->ins); - if (!ctx->fed_client->leaf_cert_ret->cert_pem) { - return -1; - } - ctx->fed_client->leaf_cert_ret->private_key_pem = refresh_cert(ctx->cert_u, - LEAF_CERTIFICATE_PRIVATE_KEY_URL, - ctx->ins); - if (!ctx->fed_client->leaf_cert_ret->private_key_pem) { - return -1; - } - ctx->fed_client->leaf_cert_ret->cert = get_cert_from_string(ctx->fed_client->leaf_cert_ret->cert_pem); - - ctx->fed_client->intermediate_cert_ret->cert_pem = refresh_cert(ctx->cert_u, - INTERMEDIATE_CERTIFICATE_URL, - ctx->ins); - if (!ctx->fed_client->intermediate_cert_ret->cert_pem) { - return -1; - } - - region = get_region(ctx->cert_u, GET_REGION_URL, ctx->region_table); - flb_plg_info(ctx->ins, "region = %s", region); - ctx->fed_client->region = region; - host = flb_sds_create_size(512); - flb_sds_snprintf(&host, flb_sds_alloc(host), "auth.%s.oci.oraclecloud.com", region); - if (!ctx->fed_u) { - upstream = flb_upstream_create(config, host, 443, - FLB_IO_TLS, ctx->ins->tls); - if (!upstream) { - return -1; - } - - ctx->fed_u = upstream; - } - ctx->fed_client->tenancy_id = get_tenancy_id_from_certificate(ctx->fed_client->leaf_cert_ret->cert); - ret = session_key_supplier(&ctx->fed_client->private_key, - &ctx->fed_client->public_key, - ctx->ins); - if (ret != 0) { - flb_plg_error(ctx->ins, "failed to create session key pair"); - return -1; - } - - ctx->fed_client->key_id = flb_sds_create_size(512); - flb_sds_snprintf(&ctx->fed_client->key_id, flb_sds_alloc(ctx->fed_client->key_id), - "%s/fed-x509/%s", ctx->fed_client->tenancy_id, fingerprint(ctx->fed_client->leaf_cert_ret->cert)); - // flb_plg_info(ctx->ins, "fed client key_id = %s", ctx->fed_client->key_id); - - // TODO: build headers - u_conn = flb_upstream_conn_get(ctx->fed_u); - if (!u_conn) { - return -1; - } - - s_leaf_cert = sanitize_certificate_string(ctx->fed_client->leaf_cert_ret->cert_pem); - // flb_plg_info(ctx->ins, "sanitized leaf cert: %s", s_leaf_cert); - s_pub_key = sanitize_certificate_string(ctx->fed_client->public_key); - // flb_plg_info(ctx->ins, "pub key: %s", s_pub_key); - s_inter_cert = sanitize_certificate_string(ctx->fed_client->intermediate_cert_ret->cert_pem); - // flb_plg_info(ctx->ins, "sanitized inter cert: %s", s_inter_cert); - sz = strlen(s_leaf_cert) + strlen(s_pub_key) + strlen(s_inter_cert); - json = flb_sds_create_size(sz + 1000); - flb_sds_snprintf(&json, flb_sds_alloc(json), - OCI_FEDERATION_REQUEST_PAYLOAD, - s_leaf_cert, - s_pub_key, - s_inter_cert); - // flb_plg_info(ctx->ins, "fed client payload = %s", json); - - fed_uri = flb_sds_create_len("/v1/x509", 8); - c = flb_http_client(u_conn, FLB_HTTP_POST, fed_uri, - json, flb_sds_len(json), - NULL, 0, NULL, 0); - c->allow_dup_headers = FLB_FALSE; - - build_federation_client_headers(ctx, c, json, fed_uri); - - /* - mk_list_foreach_safe(head, tmp, &c->headers) { - kv = mk_list_entry(head, struct flb_kv, _head); - if (flb_sds_casecmp(kv->key, "host", 4) == 0) { - flb_kv_item_destroy(kv); - break; - } - } - */ - - - ret = flb_http_do(c, &b_sent); - if (ret != 0) { - flb_plg_error(ctx->ins, "http do error"); - flb_sds_destroy(json); - flb_free(fed_uri); - flb_free(s_leaf_cert); - flb_free(s_pub_key); - flb_free(s_inter_cert); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - if (c->resp.status != 200) { - flb_plg_error(ctx->ins, "http status = %d, response = %s, header = %s", - c->resp.status, c->resp.payload, c->header_buf); - flb_sds_destroy(json); - flb_free(fed_uri); - flb_free(s_leaf_cert); - flb_free(s_pub_key); - flb_free(s_inter_cert); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - ctx->fed_client->security_token = parse_token(c->resp.payload, - c->resp.payload_size); - flb_plg_info(ctx->ins, "security token = %s", ctx->fed_client->security_token); - - err = get_token_exp(ctx->fed_client->security_token, &ctx->fed_client->expire, ctx->ins); - if (err) { - flb_plg_error(ctx->ins, "token error = %s",err); - flb_free(s_leaf_cert); - flb_free(s_pub_key); - flb_free(s_inter_cert); - flb_free(fed_uri); - flb_sds_destroy(json); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - flb_plg_info(ctx->ins, "token expiration time = %ld", ctx->fed_client->expire); - flb_free(json); - flb_free(fed_uri); - flb_free(s_leaf_cert); - flb_free(s_pub_key); - flb_free(s_inter_cert); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return 0; - -} - -static int create_pk_context(flb_sds_t filepath, const char *key_passphrase, - struct flb_oci_logan *ctx) -{ - int ret; - struct stat st; - struct file_info finfo; - FILE *fp; - flb_sds_t kbuffer; - - - ret = stat(filepath, &st); - if (ret == -1) { - flb_errno(); - flb_plg_error(ctx->ins, "cannot open key file %s", filepath); - return -1; - } - - if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { - flb_plg_error(ctx->ins, "key file is not a valid file: %s", filepath); - return -1; - } - - /* Read file content */ - if (mk_file_get_info(filepath, &finfo, MK_FILE_READ) != 0) { - flb_plg_error(ctx->ins, "error to read key file: %s", filepath); - return -1; - } - - if (!(fp = fopen(filepath, "rb"))) { - flb_plg_error(ctx->ins, "error to open key file: %s", filepath); - return -1; - } - - kbuffer = flb_sds_create_size(finfo.size + 1); - if (!kbuffer) { - flb_errno(); - fclose(fp); - return -1; - } - - ret = fread(kbuffer, finfo.size, 1, fp); - if (ret < 1) { - flb_sds_destroy(kbuffer); - fclose(fp); - flb_plg_error(ctx->ins, "fail to read key file: %s", filepath); - return -1; - } - fclose(fp); - - /* In mbedtls, for PEM, the buffer must contains a null-terminated string */ - kbuffer[finfo.size] = '\0'; - flb_sds_len_set(kbuffer, finfo.size + 1); - - ctx->private_key = kbuffer; - - return 0; -} - -static int file_to_buffer(const char *path, - char **out_buf, size_t *out_size) -{ - int ret; - char *buf; - ssize_t bytes; - FILE *fp; - struct stat st; - - if (!(fp = fopen(path, "r"))) { - return -1; - } - - ret = stat(path, &st); - if (ret == -1) { - flb_errno(); - fclose(fp); - return -1; - } - - buf = flb_calloc(1, (st.st_size + 1)); - if (!buf) { - flb_errno(); - fclose(fp); - return -1; - } - - bytes = fread(buf, st.st_size, 1, fp); - if (bytes < 1) { - flb_free(buf); - fclose(fp); - return -1; - } - - fclose(fp); - - *out_buf = buf; - *out_size = st.st_size; - - return 0; -} - -int refresh_oke_workload_security_token(struct flb_oci_logan *ctx, - struct flb_config *config) -{ - char* tmp, *host; - const char* err = NULL; - char buf[1024*8] = {0}; - size_t o_len; - int port = 12250, ret; - struct flb_tls *tls; - struct flb_http_client *c; - struct flb_connection *u_conn; - flb_sds_t auth_header; - char *token = NULL; - size_t tk_size; - flb_sds_t json; - flb_sds_t uri; - size_t b_sent; - time_t now; - - if (ctx->fed_client && ctx->fed_client->expire) { - now = time(NULL); - if (ctx->fed_client->expire > now) { - return 0; - } - } - - if (!ctx->fed_client) { - ctx->fed_client = flb_calloc(1, sizeof(struct federation_client)); - } - - /* - tmp = getenv("OCI_RESOURCE_PRINCIPAL_REGION"); - if (!tmp) { - flb_plg_error(ctx->ins, "Not a valid region"); - flb_sds_destroy(sa_cert_path); - return -1; - } - ctx->fed_client->region = flb_sds_create_len(tmp, strlen(tmp)); - */ - session_key_supplier(&ctx->fed_client->private_key, - &ctx->fed_client->public_key, - ctx->ins); - host = getenv("KUBERNETES_SERVICE_HOST"); - if (!host) { - flb_plg_error(ctx->ins, "Host not found"); - return -1; - } - if (!ctx->fed_u) { - tls = flb_tls_create(FLB_TLS_CLIENT_MODE, - 0, - 1, - NULL, - NULL, - ctx->oke_sa_ca_file, - NULL, - NULL, - NULL); - ctx->fed_u = flb_upstream_create(config, host, port, FLB_IO_TLS, tls); - } - - ret = file_to_buffer(ctx->oke_sa_token_file, &token, &tk_size); - if (ret != 0) { - flb_errno(); - flb_plg_error(ctx->ins, "failed to load kubernetes service account token"); - return -1; - } - - char *s_pub_key = sanitize_certificate_string(ctx->fed_client->public_key); - json = flb_sds_create_size(1024*4); - flb_sds_snprintf(&json, flb_sds_alloc(json), - OCI_OKE_PROXYMUX_PAYLOAD, s_pub_key); - uri = flb_sds_create_len("/resourcePrincipalSessionTokens", - sizeof("/resourcePrincipalSessionTokens") - 1); - - u_conn = flb_upstream_conn_get(ctx->fed_u); - if (!u_conn) { - flb_errno(); - flb_plg_error(ctx->ins, - "failed to establish connection with kubernetes upstream"); - return -1; - } - c = flb_http_client(u_conn, FLB_HTTP_POST, uri, json, flb_sds_len(json), NULL, 0, NULL, 0); - if (!c) { - flb_errno(); - flb_plg_error(ctx->ins, - "failed to create http client"); - flb_upstream_conn_release(u_conn); - return -1; - } - auth_header = flb_sds_create_size(1024*4); - ret = flb_sds_snprintf(&auth_header, flb_sds_alloc(auth_header), "Bearer %s", token); - flb_http_add_header(c, FLB_OCI_HEADER_AUTH, - sizeof(FLB_OCI_HEADER_AUTH) - 1, - auth_header, - ret); - flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, - sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, - "Fluent-Bit", 10); - flb_http_add_header(c, FLB_OCI_HEADER_CONTENT_TYPE, - sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, - FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL, - sizeof(FLB_OCI_HEADER_CONTENT_TYPE_FED_VAL) - 1); - flb_http_add_header(c, "Accept", 6, "*/*", 3); - ret = flb_http_do(c, &b_sent); - if (ret != 0) { - flb_plg_error(ctx->ins, "http do error"); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - if (c->resp.status != 200) { - flb_plg_info(ctx->ins, "request body = %s", json); - flb_plg_info(ctx->ins, "request header = %s", c->header_buf); - flb_plg_error(ctx->ins, - "HTTP Status = %d, payload = %s", - c->resp.status, c->resp.payload); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - - c->resp.payload++; - c->resp.payload[strlen(c->resp.payload) - 1] = '\0'; - flb_base64_decode((unsigned char*)buf, - sizeof(buf), - &o_len, - (unsigned char*) c->resp.payload, - strlen(c->resp.payload)); - ctx->key_id = parse_token(buf, strlen(buf)); - err = get_token_exp(ctx->key_id + 3, &ctx->fed_client->expire, ctx->ins); - - if (err != NULL) { - flb_plg_error(ctx->ins, - "failed to extract token expiration time"); - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - return -1; - } - flb_plg_info(ctx->ins, "token expiration time = %ld", ctx->fed_client->expire); - // decode jwt token stored in buf - // Make the request and fetch the security token - - flb_http_client_destroy(c); - flb_upstream_conn_release(u_conn); - - return 0; -} - -static int load_oci_credentials(struct flb_oci_logan *ctx) -{ - flb_sds_t content; - int found_profile = 0, res = 0; - char *line, *profile = NULL; - int eq_pos = 0; - char* key = NULL; - char* val; - - content = flb_file_read(ctx->config_file_location); - if (content == NULL || flb_sds_len(content) == 0) - { - return -1; - } - flb_plg_debug(ctx->ins, "content = %s", content); - line = strtok(content, "\n"); - while(line != NULL) { - /* process line */ - flb_plg_debug(ctx->ins, "line = %s", line); - if(!found_profile && line[0] == '[') { - profile = mk_string_copy_substr(line, 1, strlen(line) - 1); - if(!strcmp(profile, ctx->profile_name)) { - flb_plg_info(ctx->ins, "found profile"); - found_profile = 1; - goto iterate; - } - mk_mem_free(profile); - } - if(found_profile) { - if(line[0] == '[') { - break; - } - eq_pos = mk_string_char_search(line, '=', strlen(line)); - flb_plg_debug(ctx->ins, "eq_pos %d", eq_pos); - key = mk_string_copy_substr(line, 0, eq_pos); - flb_plg_debug(ctx->ins, "key = %s", key); - val = line + eq_pos + 1; - if (!key || !val) { - res = -1; - break; - } - if (strcmp(key, FLB_OCI_PARAM_USER) == 0) { - ctx->user = flb_sds_create(val); - } - else if (strcmp(key, FLB_OCI_PARAM_TENANCY) == 0) { - ctx->tenancy = flb_sds_create(val); - } - else if (strcmp(key, FLB_OCI_PARAM_KEY_FILE) == 0) { - ctx->key_file = flb_sds_create(val); - } - else if (strcmp(key, FLB_OCI_PARAM_KEY_FINGERPRINT) == 0) { - ctx->key_fingerprint = flb_sds_create(val); - } - else if (strcmp(key, FLB_OCI_PARAM_REGION) == 0) { - ctx->region = flb_sds_create(val); - } - else { - goto iterate; - } - } - iterate: - if (profile) { - mk_mem_free(profile); - profile = NULL; - } - if (key) { - mk_mem_free(key); - key = NULL; - } - line = strtok(NULL, "\n"); - } - if (!found_profile) { - flb_errno(); - res = -1; - } - - flb_sds_destroy(content); - if (profile) { - mk_mem_free(profile); - } - if (key) { - mk_mem_free(key); - } - return res; -} static int global_metadata_fields_create(struct flb_oci_logan *ctx) { @@ -1017,7 +227,7 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, return NULL; } - build_region_table(ctx); + build_region_table(&ctx->region_table); if (strcasecmp(ctx->auth_type, INSTANCE_PRINCIPAL) == 0) { ctx->cert_u = flb_upstream_create(config, METADATA_HOST_BASE, 80, FLB_IO_TCP, NULL); @@ -1061,7 +271,11 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, return NULL; } - ret = load_oci_credentials(ctx); + ret = load_oci_credentials(ctx->ins, ctx->config_file_location, + ctx->profile_name, &ctx->user, + &ctx->tenancy, &ctx->key_file, + &ctx->key_fingerprint, + &ctx->region); if (ret != 0) { flb_errno(); flb_oci_logan_conf_destroy(ctx); diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.h b/plugins/out_oracle_log_analytics/oci_logan_conf.h index 7a8f1ee0ce9..d0001054cdb 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.h +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.h @@ -30,10 +30,6 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, struct flb_config *config); int flb_oci_logan_conf_destroy(struct flb_oci_logan *ctx); -int refresh_security_token(struct flb_oci_logan *ctx, - struct flb_config *config); -int refresh_oke_workload_security_token(struct flb_oci_logan *ctx, - struct flb_config *config); int set_upstream_ctx(struct flb_oci_logan *ctx, struct flb_output_instance *ins, struct flb_config *config); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b6233d9f721..ce8523f34c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,6 +78,7 @@ set(src flb_log_event_encoder_dynamic_field.c flb_processor.c flb_reload.c + "oracle/flb_oracle_client.c" ) # Config format diff --git a/src/oracle/flb_oracle_client.c b/src/oracle/flb_oracle_client.c new file mode 100644 index 00000000000..ad17b56e7bd --- /dev/null +++ b/src/oracle/flb_oracle_client.c @@ -0,0 +1,1664 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2023 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +char* short_names[] = { + "yny\0", + "hyd\0", + "mel\0", + "bom\0", + "kix\0", + "icn\0", + "syd\0", + "nrt\0", + "yul\0", + "yyz\0", + "ams\0", + "fra\0", + "zrh\0", + "jed\0", + "dxb\0", + "gru\0", + "cwl\0", + "lhr\0", + "iad\0", + "phx\0", + "sjc\0", + "vcp\0", + "scl\0", + "mtz\0", + "mrs\0", + "sin\0", + "auh\0", + "lin\0", + "arn\0", + "jnb\0", + "cdg\0", + "qro\0", + "mad\0", + "ord\0", + "lfi\0", + "luf\0", + "ric\0", + "pia\0", + "tus\0", + "ltn\0", + "brs\0", + "nja\0", + "ukb\0", + "mct\0", + "wga\0", + "bgy\0", + "mxp\0", + "snn\0", + "dtm\0", + "dus\0", + "ork\0", + "vll\0", + "str\0", + "beg\0", + NULL +}; + +char *long_names[] = { + "ap-chuncheon-1\0", + "ap-hyderabad-1\0", + "ap-melbourne-1\0", + "ap-mumbai-1\0", + "ap-osaka-1\0", + "ap-seoul-1\0", + "ap-sydney-1\0", + "ap-tokyo-1\0", + "ca-montreal-1\0", + "ca-toronto-1\0", + "eu-amsterdam-1\0", + "eu-frankfurt-1\0", + "eu-zurich-1\0", + "me-jeddah-1\0", + "me-dubai-1\0", + "sa-saopaulo-1\0", + "uk-cardiff-1\0", + "uk-london-1\0", + "us-ashburn-1\0", + "us-phoenix-1\0", + "us-sanjose-1\0", + "sa-vinhedo-1\0", + "sa-santiago-1\0", + "il-jerusalem-1\0", + "eu-marseille-1\0", + "ap-singapore-1\0", + "me-abudhabi-1\0", + "eu-milan-1\0", + "eu-stockholm-1\0", + "af-johannesburg-1\0", + "eu-paris-1\0", + "mx-queretaro-1\0", + "eu-madrid-1\0", + "us-chicago-1\0", + "us-langley-1\0", + "us-luke-1\0", + "us-gov-ashburn-1\0", + "us-gov-chicago-1\0", + "us-gov-phoenix-1\0", + "uk-gov-london-1\0", + "uk-gov-cardiff-1\0", + "ap-chiyoda-1\0", + "ap-ibaraki-1\0", + "me-dcc-muscat-1\0", + "ap-dcc-canberra-1\0", + "eu-dcc-milan-1\0", + "eu-dcc-milan-2\0", + "eu-dcc-dublin-2\0", + "eu-dcc-rating-2\0", + "eu-dcc-rating-1\0", + "eu-dcc-dublin-1\0", + "eu-madrid-2\0", + "eu-frankfurt-2\0", + "eu-jovanovac-1\0", + NULL +}; + +int create_pk_context(flb_sds_t filepath, + const char *key_passphrase, + struct flb_output_instance *ins, + flb_sds_t *p_key) +{ + int ret; + struct stat st; + struct file_info finfo; + FILE *fp; + flb_sds_t kbuffer; + + + ret = stat(filepath, &st); + if (ret == -1) { + flb_errno(); + flb_plg_error(ins, "cannot open key file %s", filepath); + return -1; + } + + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { + flb_plg_error(ins, "key file is not a valid file: %s", filepath); + return -1; + } + + /* Read file content */ + if (mk_file_get_info(filepath, &finfo, MK_FILE_READ) != 0) { + flb_plg_error(ins, "error to read key file: %s", filepath); + return -1; + } + + if (!(fp = fopen(filepath, "rb"))) { + flb_plg_error(ins, "error to open key file: %s", filepath); + return -1; + } + + kbuffer = flb_sds_create_size(finfo.size + 1); + if (!kbuffer) { + flb_errno(); + fclose(fp); + return -1; + } + + ret = fread(kbuffer, finfo.size, 1, fp); + if (ret < 1) { + flb_sds_destroy(kbuffer); + fclose(fp); + flb_plg_error(ins, "fail to read key file: %s", filepath); + return -1; + } + fclose(fp); + + /* In mbedtls, for PEM, the buffer must contains a null-terminated string */ + kbuffer[finfo.size] = '\0'; + flb_sds_len_set(kbuffer, finfo.size + 1); + + *p_key = kbuffer; + + return 0; +} + +int load_oci_credentials(struct flb_output_instance *ins, + flb_sds_t config_file_location, + flb_sds_t profile_name, + flb_sds_t *user, flb_sds_t *tenancy, + flb_sds_t *key_file, flb_sds_t *key_fingerprint, + flb_sds_t *region) +{ + flb_sds_t content; + int found_profile = 0, res = 0; + char *line, *profile = NULL; + int eq_pos = 0; + char* key = NULL; + char* val; + + content = flb_file_read(config_file_location); + if (content == NULL || flb_sds_len(content) == 0) + { + return -1; + } + flb_plg_debug(ins, "content = %s", content); + line = strtok(content, "\n"); + while(line != NULL) { + /* process line */ + flb_plg_debug(ins, "line = %s", line); + if(!found_profile && line[0] == '[') { + profile = mk_string_copy_substr(line, 1, strlen(line) - 1); + if(!strcmp(profile, profile_name)) { + flb_plg_info(ins, "found profile"); + found_profile = 1; + goto iterate; + } + mk_mem_free(profile); + } + if(found_profile) { + if(line[0] == '[') { + break; + } + eq_pos = mk_string_char_search(line, '=', strlen(line)); + flb_plg_debug(ins, "eq_pos %d", eq_pos); + key = mk_string_copy_substr(line, 0, eq_pos); + flb_plg_debug(ins, "key = %s", key); + val = line + eq_pos + 1; + if (!key || !val) { + res = -1; + break; + } + if (strcmp(key, FLB_OCI_PARAM_USER) == 0) { + *user = flb_sds_create(val); + } + else if (strcmp(key, FLB_OCI_PARAM_TENANCY) == 0) { + *tenancy = flb_sds_create(val); + } + else if (strcmp(key, FLB_OCI_PARAM_KEY_FILE) == 0) { + *key_file = flb_sds_create(val); + } + else if (strcmp(key, FLB_OCI_PARAM_KEY_FINGERPRINT) == 0) { + *key_fingerprint = flb_sds_create(val); + } + else if (strcmp(key, FLB_OCI_PARAM_REGION) == 0) { + *region = flb_sds_create(val); + } + else { + goto iterate; + } + } + iterate: + if (profile) { + mk_mem_free(profile); + profile = NULL; + } + if (key) { + mk_mem_free(key); + key = NULL; + } + line = strtok(NULL, "\n"); + } + if (!found_profile) { + flb_errno(); + res = -1; + } + + flb_sds_destroy(content); + if (profile) { + mk_mem_free(profile); + } + if (key) { + mk_mem_free(key); + } + return res; +} + +/* + * Authorization: Signature version="1",keyId="//", + * algorithm="rsa-sha256",headers="(request-target) date x-content-sha256 content-type content-length", + * signature="signature" + */ +flb_sds_t create_authorization_header_content(flb_sds_t key_id, + flb_sds_t signature) +{ + flb_sds_t content; + + content = flb_sds_create_size(512); + flb_sds_cat_safe(&content, FLB_OCI_SIGN_SIGNATURE_VERSION, + sizeof(FLB_OCI_SIGN_SIGNATURE_VERSION) - 1); + flb_sds_cat_safe(&content, ",", 1); + flb_sds_cat_safe(&content, FLB_OCI_SIGN_KEYID, + sizeof(FLB_OCI_SIGN_KEYID) - 1); + flb_sds_cat_safe(&content, "=\"", 2); + flb_sds_cat_safe(&content, key_id, flb_sds_len(key_id)); + flb_sds_cat_safe(&content, "\",", 2); + flb_sds_cat_safe(&content, FLB_OCI_SIGN_ALGORITHM, + sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); + flb_sds_cat_safe(&content, ",", 1); + flb_sds_cat_safe(&content, FLB_OCI_SIGN_HEADERS, + sizeof(FLB_OCI_SIGN_HEADERS) - 1); + flb_sds_cat_safe(&content, ",", 1); + flb_sds_cat_safe(&content, FLB_OCI_SIGN_SIGNATURE, + sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); + flb_sds_cat_safe(&content, "=\"", 2); + flb_sds_cat_safe(&content, signature, flb_sds_len(signature)); + flb_sds_cat_safe(&content, "\"", 1); + + return content; +} + +flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, + flb_sds_t signing_string, + struct flb_output_instance *ins) +{ + int len = 0, ret; + size_t outlen; + flb_sds_t signature; + unsigned char sha256_buf[32] = { 0 }; + unsigned char sig[256] = { 0 }; + size_t sig_len = sizeof(sig); + + ret = flb_hash_simple(FLB_HASH_SHA256, + (unsigned char*) signing_string, + flb_sds_len(signing_string), + sha256_buf, sizeof(sha256_buf)); + + if(ret != FLB_CRYPTO_SUCCESS) { + flb_plg_error(ins, "error generating hash buffer"); + return NULL; + } + + ret = flb_crypto_sign_simple(FLB_CRYPTO_PRIVATE_KEY, + FLB_CRYPTO_PADDING_PKCS1, + FLB_HASH_SHA256, + (unsigned char *) private_key, + flb_sds_len(private_key), + sha256_buf, sizeof(sha256_buf), + sig, &sig_len); + + + if (ret != FLB_CRYPTO_SUCCESS) { + flb_plg_error(ins, "error signing SHA256"); + return NULL; + } + + signature = flb_sds_create_size(512); + if (!signature) { + flb_errno(); + return NULL; + } + + /* base 64 encode */ + len = flb_sds_alloc(signature) - 1; + flb_base64_encode((unsigned char*) signature, len, &outlen, sig, + sizeof(sig)); + signature[outlen] = '\0'; + flb_sds_len_set(signature, outlen); + + return signature; +} + +flb_sds_t get_date(void) +{ + + flb_sds_t rfc1123date; + time_t t; + size_t size; + struct tm tm = { 0 }; + + /* Format Date */ + rfc1123date = flb_sds_create_size(32); + if (!rfc1123date) { + flb_errno(); + return NULL; + } + + t = time(NULL); + if (!gmtime_r(&t, &tm)) { + flb_errno(); + flb_sds_destroy(rfc1123date); + return NULL; + } + size = strftime(rfc1123date, flb_sds_alloc(rfc1123date) - 1, + "%a, %d %b %Y %H:%M:%S GMT", &tm); + if (size <= 0) { + flb_errno(); + flb_sds_destroy(rfc1123date); + return NULL; + } + flb_sds_len_set(rfc1123date, size); + return rfc1123date; +} + +flb_sds_t add_header_and_signing(struct flb_http_client *c, + flb_sds_t signing_str, const char *header, int headersize, + const char *val, int val_size) +{ + if (!signing_str) { + return NULL; + } + + flb_http_add_header(c, header, headersize, val, val_size); + + flb_sds_cat_safe(&signing_str, "\n", 1); + flb_sds_cat_safe(&signing_str, header, headersize); + flb_sds_cat_safe(&signing_str, ": ", 2); + flb_sds_cat_safe(&signing_str, val, val_size); + + return signing_str; +} + +int build_federation_client_headers(struct flb_http_client *c, flb_sds_t private_key, + flb_sds_t key_id, flb_sds_t json, + flb_sds_t uri, struct flb_output_instance *ins) +{ + int ret = -1; + flb_sds_t tmp_sds = NULL; + flb_sds_t signing_str = NULL; + flb_sds_t rfc1123date = NULL; + flb_sds_t encoded_uri = NULL; + flb_sds_t signature = NULL; + flb_sds_t auth_header_str = NULL; + + size_t tmp_len = 0; + + unsigned char sha256_buf[32] = { 0 }; + + tmp_sds = flb_sds_create_size(512); + if (!tmp_sds) { + flb_errno(); + goto error_label; + } + + signing_str = flb_sds_create_size(1024); + if (!signing_str) { + flb_errno(); + goto error_label; + } + + // Add (requeset-target) to signing string + encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); + if (!encoded_uri) { + flb_errno(); + goto error_label; + } + signing_str = flb_sds_cat(signing_str, FLB_OCI_HEADER_REQUEST_TARGET, + sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); + signing_str = flb_sds_cat(signing_str, ": post ", sizeof(": post ") - 1); + signing_str = flb_sds_cat(signing_str, encoded_uri, + flb_sds_len(encoded_uri)); + + // Add Date header + rfc1123date = get_date(); + if (!rfc1123date) { + flb_plg_error(ins, "cannot compose temporary date header"); + goto error_label; + } + signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_DATE, + sizeof(FLB_OCI_HEADER_DATE) - 1, rfc1123date, + flb_sds_len(rfc1123date)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + // Add x-content-sha256 Header + ret = flb_hash_simple(FLB_HASH_SHA256, + (unsigned char*) json, + flb_sds_len(json), + sha256_buf, sizeof(sha256_buf)); + + if (ret != FLB_CRYPTO_SUCCESS) { + flb_plg_error(ins, "error forming hash buffer for x-content-sha256 Header"); + goto error_label; + } + + flb_base64_encode((unsigned char*) tmp_sds, flb_sds_len(tmp_sds) - 1, + &tmp_len, sha256_buf, sizeof(sha256_buf)); + + tmp_sds[tmp_len] = '\0'; + flb_sds_len_set(tmp_sds, tmp_len); + + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_X_CONTENT_SHA256, + sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds, + flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + // Add content-Type + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, + FLB_OCI_HEADER_CONTENT_TYPE_JSON, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE_JSON) - 1); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + // Add content-Length + tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", + (int) strlen(json)); + flb_sds_len_set(tmp_sds, tmp_len); + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_LENGTH, sizeof(FLB_OCI_HEADER_CONTENT_LENGTH) - 1, + tmp_sds, flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + // Add Authorization header + signature = create_base64_sha256_signature(private_key, + signing_str,ins); + if (!signature) { + flb_plg_error(ins, "cannot compose signing signature"); + goto error_label; + } + + auth_header_str = create_fed_authorization_header_content(signature, key_id); + if (!auth_header_str) { + flb_plg_error(ins, "cannot compose authorization header"); + goto error_label; + } + + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, + auth_header_str, flb_sds_len(auth_header_str)); + + // User-Agent + flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, + sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, + FLB_OCI_HEADER_USER_AGENT_VAL, + sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); + + // Accept + flb_http_add_header(c, "Accept", 6, "*/*", 3); + + ret = 0; + + error_label: + if (tmp_sds) { + flb_sds_destroy(tmp_sds); + } + if (signing_str) { + flb_sds_destroy(signing_str); + } + if (rfc1123date) { + flb_sds_destroy(rfc1123date); + } + if (encoded_uri) { + flb_sds_destroy(encoded_uri); + } + if (signature) { + flb_sds_destroy(signature); + } + if (auth_header_str) { + flb_sds_destroy(auth_header_str); + } + return ret; + +} + +int build_headers(struct flb_http_client *c, flb_sds_t private_key, + flb_sds_t key_id, flb_sds_t json, + flb_sds_t uri, struct flb_output_instance *ins, + char *content_type) +{ + int ret = -1; + flb_sds_t tmp_sds = NULL; + flb_sds_t signing_str = NULL; + flb_sds_t rfc1123date = NULL; + flb_sds_t encoded_uri = NULL; + flb_sds_t signature = NULL; + flb_sds_t auth_header_str = NULL; + + flb_sds_t tmp_ref = NULL; + + size_t tmp_len = 0; + + unsigned char sha256_buf[32] = { 0 }; + + tmp_sds = flb_sds_create_size(512); + if (!tmp_sds) { + flb_errno(); + goto error_label; + } + + signing_str = flb_sds_create_size(1024); + if (!signing_str) { + flb_errno(); + goto error_label; + } + + /* Add (requeset-target) to signing string */ + encoded_uri = flb_uri_encode(uri, flb_sds_len(uri)); + if (!encoded_uri) { + flb_errno(); + goto error_label; + } + flb_sds_cat_safe(&signing_str, FLB_OCI_HEADER_REQUEST_TARGET, + sizeof(FLB_OCI_HEADER_REQUEST_TARGET) - 1); + flb_sds_cat_safe(&signing_str, ": post ", sizeof(": post ") - 1); + flb_sds_cat_safe(&signing_str, encoded_uri, + flb_sds_len(encoded_uri)); + + /* Add Host to Header */ + if (((c->flags & FLB_IO_TLS) && c->port == 443) + || (!(c->flags & FLB_IO_TLS) && c->port == 80)) { + /* default port */ + tmp_ref = flb_sds_copy(tmp_sds, c->host, strlen(c->host)); + } + else { + tmp_ref = flb_sds_printf(&tmp_sds, "%s:%i", c->host, c->port); + } + if (!tmp_ref) { + flb_plg_error(ins, "cannot compose temporary host header"); + goto error_label; + } + tmp_sds = tmp_ref; + tmp_ref = NULL; + + signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_HOST, + sizeof(FLB_OCI_HEADER_HOST) - 1, + tmp_sds, flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + /* Add Date header */ + rfc1123date = get_date(); + if (!rfc1123date) { + flb_plg_error(ins, "cannot compose temporary date header"); + goto error_label; + } + signing_str = add_header_and_signing(c, signing_str, FLB_OCI_HEADER_DATE, + sizeof(FLB_OCI_HEADER_DATE) - 1, rfc1123date, + flb_sds_len(rfc1123date)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + /* Add x-content-sha256 Header */ + ret = flb_hash_simple(FLB_HASH_SHA256, + (unsigned char*) json, + flb_sds_len(json), + sha256_buf, sizeof(sha256_buf)); + + if (ret != FLB_CRYPTO_SUCCESS) { + flb_plg_error(ins, "error forming hash buffer for x-content-sha256 Header"); + goto error_label; + } + + flb_base64_encode((unsigned char*) tmp_sds, flb_sds_len(tmp_sds) - 1, + &tmp_len, sha256_buf, sizeof(sha256_buf)); + + tmp_sds[tmp_len] = '\0'; + flb_sds_len_set(tmp_sds, tmp_len); + + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_X_CONTENT_SHA256, + sizeof(FLB_OCI_HEADER_X_CONTENT_SHA256) - 1, tmp_sds, + flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + /* Add content-Type */ + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_TYPE, sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, + content_type, + sizeof(content_type) - 1); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + /* Add content-Length */ + tmp_len = snprintf(tmp_sds, flb_sds_alloc(tmp_sds) - 1, "%i", + (int) flb_sds_len(json)); + flb_sds_len_set(tmp_sds, tmp_len); + signing_str = add_header_and_signing(c, signing_str, + FLB_OCI_HEADER_CONTENT_LENGTH, sizeof(FLB_OCI_HEADER_CONTENT_LENGTH) - 1, + tmp_sds, flb_sds_len(tmp_sds)); + if (!signing_str) { + flb_plg_error(ins, "cannot compose signing string"); + goto error_label; + } + + /* Add Authorization header */ + signature = create_base64_sha256_signature(private_key, signing_str, ins); + if (!signature) { + flb_plg_error(ins, "cannot compose signing signature"); + goto error_label; + } + + auth_header_str = create_authorization_header_content(key_id, signature); + if (!auth_header_str) { + flb_plg_error(ins, "cannot compose authorization header"); + goto error_label; + } + + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, sizeof(FLB_OCI_HEADER_AUTH) - 1, + auth_header_str, flb_sds_len(auth_header_str)); + + /* User-Agent */ + flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, + sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, + FLB_OCI_HEADER_USER_AGENT_VAL, + sizeof(FLB_OCI_HEADER_USER_AGENT_VAL) - 1); + + /* Accept */ + flb_http_add_header(c, "Accept", 6, "*/*", 3); + + ret = 0; + + error_label: + if (tmp_sds) { + flb_sds_destroy(tmp_sds); + } + if (signing_str) { + flb_sds_destroy(signing_str); + } + if (rfc1123date) { + flb_sds_destroy(rfc1123date); + } + if (encoded_uri) { + flb_sds_destroy(encoded_uri); + } + if (signature) { + flb_sds_destroy(signature); + } + if (auth_header_str) { + flb_sds_destroy(auth_header_str); + } + return ret; +} + + +flb_sds_t refresh_cert(struct flb_upstream *u, + flb_sds_t cert_url, + struct flb_output_instance *ins) +{ + flb_sds_t cert = NULL; + struct flb_connection *u_conn; + struct flb_http_client *c; + int ret = 0; + size_t b_sent; + u_conn = flb_upstream_conn_get(u); + if (!u_conn) { + flb_errno(); + return NULL; + } + + c = flb_http_client(u_conn, FLB_HTTP_GET, cert_url, NULL, 0, + NULL, 0, NULL, 0); + + if (!c) { + flb_errno(); + flb_upstream_conn_release(u_conn); + return NULL; + } + + flb_http_strip_port_from_host(c); + flb_http_buffer_size(c, 0); + flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); + + ret = flb_http_do(c, &b_sent); + + if (ret != 0) { + flb_errno(); + flb_plg_error(ins, "http do error"); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + if (c->resp.status != 200 && c->resp.status != 204 && c->resp.status != 201) { + flb_errno(); + flb_plg_info(ins, "request header = %s", c->header_buf); + flb_plg_error(ins, "request was not successful with status = %d payload = %s url = %s", + c->resp.status, c->resp.payload, cert_url); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + cert = flb_sds_create_len(c->resp.payload, c->resp.payload_size); + + if (!cert) { + flb_errno(); + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return cert; +} + +// finish this func +flb_sds_t get_tenancy_id_from_certificate(X509 *cert) +{ + flb_sds_t t_id = NULL; + const unsigned char *str; + char* x; + + X509_NAME *subj = X509_get_subject_name(cert); + + for (int i = 0; i < X509_NAME_entry_count(subj); i++) { + X509_NAME_ENTRY *e = X509_NAME_get_entry(subj, i); + ASN1_STRING *d = X509_NAME_ENTRY_get_data(e); + str = ASN1_STRING_get0_data(d); + x = strstr((const char *) str, "opc-tenant:"); + if (x) { + break; + } + } + + t_id = flb_sds_create((const char*) str + 11); + + return t_id; +} + +char* sanitize_certificate_string(flb_sds_t cert_pem) +{ + // i2d_X509() + char sanitized[strlen(cert_pem) + 1]; + strcpy(sanitized, cert_pem); + char c_start[] = "-----BEGIN CERTIFICATE-----"; + size_t c_st_len = strlen(c_start); + char c_end[] = "-----END CERTIFICATE-----"; + char k_start[] = "-----BEGIN PUBLIC KEY-----"; + size_t k_st_len = strlen(k_start); + char k_end[] = "-----END PUBLIC KEY-----"; + char *p = NULL, *q = NULL, *ans, *tmp, *a; + + p = strstr(sanitized, c_start); + q = strstr(sanitized, c_end); + if (p && q) { + *q = '\0'; + tmp = p + c_st_len + 1; + } + else { + p = strstr(sanitized, k_start); + q = strstr(sanitized, k_end); + *q = '\0'; + tmp = p + k_st_len; + } + ans = flb_malloc(strlen(sanitized) + sizeof(char)); + a = ans; + while(*tmp != '\0') + { + if(*tmp != '\t' && *tmp != '\n') { + *a++ = *tmp++; + } + else { + ++tmp; + } + } + *a = '\0'; + + return ans; + +} + +void colon_separated_fingerprint(unsigned char* readbuf, void *writebuf, size_t len) +{ + char *l; + for(size_t i=0; i < len-1; i++) { + l = (char*) (3*i + ((intptr_t) writebuf)); + sprintf(l, "%02x:", readbuf[i]); + } + + l = (char*) (3*(len - 1) + ((intptr_t) writebuf)); + sprintf(l, "%02x", readbuf[len - 1]); +} + +flb_sds_t fingerprint(X509 *cert) +{ + // i2d_X509() + flb_sds_t fingerprint = NULL; + const EVP_MD *digest; + unsigned char md[SHA_DIGEST_LENGTH]; + char buf[3*SHA_DIGEST_LENGTH+1]; + unsigned int n; + + digest = EVP_get_digestbyname("sha1"); + X509_digest(cert, digest, md, &n); + + colon_separated_fingerprint(md, (void *) buf, (size_t) SHA_DIGEST_LENGTH); + + fingerprint = flb_sds_create_len(buf, 3*SHA_DIGEST_LENGTH); + return fingerprint; +} + +int session_key_supplier(flb_sds_t *priv_key, + flb_sds_t *pub_key, + struct flb_output_instance *ins) +{ + // Key generation + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + EVP_PKEY* key = NULL; + BIO *pri, *pub; + int priKeyLen; + int pubKeyLen; + char* priKeyStr; + char* pubKeyStr; + int ret; + BIGNUM *bne = NULL; + + bne = BN_new(); + ret = BN_set_word(bne, RSA_EXP); + if (ret != 1) { + return -1; + } + EVP_PKEY_keygen_init(ctx); + EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bne); + EVP_PKEY_keygen(ctx, &key); + EVP_PKEY_CTX_free(ctx); + + // Serialize to string + pri = BIO_new(BIO_s_mem()); + pub = BIO_new(BIO_s_mem()); + PEM_write_bio_PrivateKey_traditional(pri, key, NULL, NULL, 0, 0, NULL); + PEM_write_bio_PUBKEY(pub, key); + + priKeyLen = BIO_pending(pri); + pubKeyLen = BIO_pending(pub); + priKeyStr = flb_malloc(priKeyLen); + pubKeyStr = flb_malloc(pubKeyLen); + BIO_read(pri, priKeyStr, priKeyLen); + BIO_read(pub, pubKeyStr, pubKeyLen); + priKeyStr[priKeyLen] = '\0'; + pubKeyStr[pubKeyLen] = '\0'; + // flb_plg_info(ins, "private_key = %s", priKeyStr); + // flb_plg_info(ins, "pub_key = %s", pubKeyStr); + + *priv_key = flb_sds_create_len((const char *) priKeyStr, priKeyLen); + *pub_key = flb_sds_create_len((const char *)pubKeyStr, pubKeyLen); + + BIO_free(pri); + BIO_free(pub); + flb_free(priKeyStr); + flb_free(pubKeyStr); + BN_free(bne); + + return 0; +} + +X509 *get_cert_from_string(flb_sds_t cert_pem) +{ + X509 *cert; + BIO* certBio = BIO_new(BIO_s_mem()); + BIO_write(certBio, cert_pem, (int) flb_sds_len(cert_pem)); + cert = PEM_read_bio_X509(certBio, NULL, NULL, NULL); + + BIO_free(certBio); + return cert; +} + +flb_sds_t get_region(struct flb_upstream *u, + flb_sds_t region_url, + struct flb_hash_table *ht) +{ + flb_sds_t region; + char* temp_region = NULL; + struct flb_connection *u_conn; + struct flb_http_client *c; + size_t b_sent, temp_sz; + int ret; + + // TODO: construct region uri + u_conn = flb_upstream_conn_get(u); + if (!u_conn) { + flb_errno(); + return NULL; + } + + c = flb_http_client(u_conn, FLB_HTTP_GET, region_url, + NULL, 0, NULL, 0, NULL, 0); + if (!c) { + flb_errno(); + return NULL; + } + + flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + flb_http_add_header(c, "Authorization", 13, "Bearer Oracle", 13); + + ret = flb_http_do(c, &b_sent); + + if (ret != 0) { + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + if (c->resp.status != 200 && c->resp.status != 201 && + c->resp.status != 204) { + flb_upstream_conn_release(u_conn); + flb_http_client_destroy(c); + return NULL; + } + + ret = flb_hash_table_get(ht, mk_string_tolower(c->resp.payload), + (int)c->resp.payload_size, + (void *)&temp_region, + &temp_sz); + if (ret < 0) { + temp_region = c->resp.payload; + temp_sz = c->resp.payload_size; + } + + region = flb_sds_create_len(temp_region, + (int) temp_sz); + + return region; +} + +flb_sds_t parse_token(char *response, + size_t response_len) +{ + int tok_size = 32, ret, i; + jsmn_parser parser; + jsmntok_t *t; + jsmntok_t *tokens; + char *key; + char *val; + int key_len; + int val_len; + flb_sds_t token = NULL; + + jsmn_init(&parser); + + tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); + if (!tokens) { + flb_errno(); + return NULL; + } + + ret = jsmn_parse(&parser, response, response_len, tokens, tok_size); + + if (ret<=0) { + flb_free(tokens); + return NULL; + } + tok_size = ret; + + /* Parse JSON tokens */ + for (i = 0; i < tok_size; i++) { + t = &tokens[i]; + + if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { + break; + } + + if (t->type != JSMN_STRING) { + continue; + } + + key = response + t->start; + key_len = (t->end - t->start); + + i++; + t = &tokens[i]; + val = response + t->start; + val_len = (t->end - t->start); + + if (val_len < 1) { + continue; + } + + if ((key_len == sizeof(FLB_OCI_TOKEN) - 1) + && strncasecmp(key, FLB_OCI_TOKEN, + sizeof(FLB_OCI_TOKEN) - 1) == 0) { + // code + token = flb_sds_create_len(val, val_len); + if (!token) { + flb_free(tokens); + return NULL; + } + break; + } + } + + flb_free(tokens); + return token; +} + +static const char *jwt_decode_payload(const char *src, + char **bufplainp) { + char *converted_src; + char *payload = NULL; + + const char *errstr = NULL; + + int i, padding, len; + + int payload_len; + int nbytesdecoded; + + int payloads_start = 0; + int payloads_end = 0; + + len = (int)strlen(src); + converted_src = flb_malloc(len + 4); + + for (i = 0; i < len; i++) { + switch (src[i]) { + case '-': + converted_src[i] = '+'; + break; + + case '_': + converted_src[i] = '/'; + break; + + case '.': + if (payloads_start == 0) + payloads_start = i + 1; + else { + if (payloads_end > 0) { + errstr = + "The token is invalid with more " + "than 2 delimiters"; + goto done; + } + payloads_end = i; + } + /* FALLTHRU */ + + default: + converted_src[i] = src[i]; + } + } + + if (payloads_start == 0 || payloads_end == 0) { + errstr = "The token is invalid with less than 2 delimiters"; + goto done; + } + + payload_len = payloads_end - payloads_start; + payload = flb_malloc(payload_len + 4); + strncpy(payload, (converted_src + payloads_start), payload_len); + + padding = 4 - (payload_len % 4); + if (padding < 4) { + while (padding--) + payload[payload_len++] = '='; + } + + nbytesdecoded = ((payload_len + 3) / 4) * 3; + *bufplainp = flb_malloc(nbytesdecoded + 1); + + if (EVP_DecodeBlock((uint8_t *)(*bufplainp), (uint8_t *)payload, + (int)payload_len) == -1) { + errstr = "Failed to decode base64 payload"; + } + + done: + flb_free(payload); + flb_free(converted_src); + return errstr; +} + +const char* get_token_exp(flb_sds_t token_string, + time_t *exp, + struct flb_output_instance *ins) +{ + char *payload = NULL; + const char* err_str = NULL; + + err_str = jwt_decode_payload(token_string, &payload); + // flb_plg_info(ins, "jwt payload = %s", payload); + + if (err_str != NULL) { + return err_str; + } + + int tok_size = 256, ret, i; + jsmn_parser parser; + jsmntok_t *t; + jsmntok_t *tokens; + char *key; + char *val; + int key_len; + int val_len; + flb_sds_t token = NULL; + + jsmn_init(&parser); + + tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size); + if (!tokens) { + flb_errno(); + return NULL; + } + + ret = jsmn_parse(&parser, payload, strlen(payload), tokens, tok_size); + + if (ret<=0) { + flb_free(tokens); + return NULL; + } + tok_size = ret; + + /* Parse JSON tokens */ + for (i = 0; i < tok_size; i++) { + t = &tokens[i]; + + if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { + break; + } + + if (t->type != JSMN_STRING) { + continue; + } + + key = payload + t->start; + key_len = (t->end - t->start); + + i++; + t = &tokens[i]; + val = payload + t->start; + val_len = (t->end - t->start); + + if (val_len < 1) { + continue; + } + + // flb_plg_info(ins, "sectoken %s: %s", key, val); + if ((key_len == 3) + && strncasecmp(key, "exp", + 3) == 0) { + // code + flb_plg_info(ins, "fetched exp time = %s", val); + *exp = atol(val); + break; + } + } + + flb_free(tokens); + return err_str; +} + +void build_region_table(struct flb_hash_table **region_table) { + *region_table = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE, 100, 0); + int i; + for(i = 0; short_names[i] != NULL; i++) { + flb_hash_table_add(*region_table, + short_names[i], + strlen(short_names[i]), + long_names[i], + strlen(long_names[i])); + } + +} + +int refresh_security_token(struct federation_client *fed_client, + struct flb_config *config, + struct flb_output_instance *ins, + struct flb_upstream *fed_u, + struct flb_upstream *cert_u, + struct flb_hash_table *region_table) +{ + flb_sds_t region; + flb_sds_t host; + flb_sds_t fed_uri; + char* err; + struct flb_upstream *upstream; + struct flb_connection *u_conn; + struct flb_http_client *c; + struct flb_kv *kv; + struct mk_list *tmp; + struct mk_list *head; + char *s_leaf_cert, *s_inter_cert, *s_pub_key; + int ret = -1, sz; + time_t now; + size_t b_sent; + flb_sds_t json; + if (fed_client && fed_client->expire) { + now = time(NULL); + if (fed_client->expire > now) { + return 0; + } + } + if (!fed_client) { + fed_client = flb_calloc(1, sizeof(struct federation_client)); + } + if (!fed_client->leaf_cert_ret) { + fed_client->leaf_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); + } + if (!fed_client->intermediate_cert_ret) { + fed_client->intermediate_cert_ret = flb_calloc(1, sizeof(struct cert_retriever)); + } + + fed_client->leaf_cert_ret->cert_pem = refresh_cert(cert_u, + LEAF_CERTIFICATE_URL, + ins); + if (!fed_client->leaf_cert_ret->cert_pem) { + return -1; + } + fed_client->leaf_cert_ret->private_key_pem = refresh_cert(cert_u, + LEAF_CERTIFICATE_PRIVATE_KEY_URL, + ins); + if (!fed_client->leaf_cert_ret->private_key_pem) { + return -1; + } + fed_client->leaf_cert_ret->cert = get_cert_from_string(fed_client->leaf_cert_ret->cert_pem); + + fed_client->intermediate_cert_ret->cert_pem = refresh_cert(cert_u, + INTERMEDIATE_CERTIFICATE_URL, + ins); + if (!fed_client->intermediate_cert_ret->cert_pem) { + return -1; + } + + region = get_region(cert_u, GET_REGION_URL, region_table); + flb_plg_info(ins, "region = %s", region); + fed_client->region = region; + host = flb_sds_create_size(512); + flb_sds_snprintf(&host, flb_sds_alloc(host), "auth.%s.oci.oraclecloud.com", region); + if (!fed_u) { + upstream = flb_upstream_create(config, host, 443, + FLB_IO_TLS, ins->tls); + if (!upstream) { + return -1; + } + + fed_u = upstream; + } + fed_client->tenancy_id = get_tenancy_id_from_certificate(fed_client->leaf_cert_ret->cert); + ret = session_key_supplier(&fed_client->private_key, + &fed_client->public_key, + ins); + if (ret != 0) { + flb_plg_error(ins, "failed to create session key pair"); + return -1; + } + + fed_client->key_id = flb_sds_create_size(512); + flb_sds_snprintf(&fed_client->key_id, flb_sds_alloc(fed_client->key_id), + "%s/fed-x509/%s", fed_client->tenancy_id, fingerprint(fed_client->leaf_cert_ret->cert)); + // flb_plg_info(ctx->ins, "fed client key_id = %s", ctx->fed_client->key_id); + + // TODO: build headers + u_conn = flb_upstream_conn_get(fed_u); + if (!u_conn) { + return -1; + } + + s_leaf_cert = sanitize_certificate_string(fed_client->leaf_cert_ret->cert_pem); + // flb_plg_info(ctx->ins, "sanitized leaf cert: %s", s_leaf_cert); + s_pub_key = sanitize_certificate_string(fed_client->public_key); + // flb_plg_info(ctx->ins, "pub key: %s", s_pub_key); + s_inter_cert = sanitize_certificate_string(fed_client->intermediate_cert_ret->cert_pem); + // flb_plg_info(ctx->ins, "sanitized inter cert: %s", s_inter_cert); + sz = strlen(s_leaf_cert) + strlen(s_pub_key) + strlen(s_inter_cert); + json = flb_sds_create_size(sz + 1000); + flb_sds_snprintf(&json, flb_sds_alloc(json), + OCI_FEDERATION_REQUEST_PAYLOAD, + s_leaf_cert, + s_pub_key, + s_inter_cert); + // flb_plg_info(ctx->ins, "fed client payload = %s", json); + + fed_uri = flb_sds_create_len("/v1/x509", 8); + c = flb_http_client(u_conn, FLB_HTTP_POST, fed_uri, + json, flb_sds_len(json), + NULL, 0, NULL, 0); + c->allow_dup_headers = FLB_FALSE; + + build_federation_client_headers(c, fed_client->leaf_cert_ret->private_key_pem, + fed_client->key_id, json, + fed_uri, ins); + /* + mk_list_foreach_safe(head, tmp, &c->headers) { + kv = mk_list_entry(head, struct flb_kv, _head); + if (flb_sds_casecmp(kv->key, "host", 4) == 0) { + flb_kv_item_destroy(kv); + break; + } + } + */ + + + ret = flb_http_do(c, &b_sent); + if (ret != 0) { + flb_plg_error(ins, "http do error"); + flb_sds_destroy(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + if (c->resp.status != 200) { + flb_plg_error(ins, "http status = %d, response = %s, header = %s", + c->resp.status, c->resp.payload, c->header_buf); + flb_sds_destroy(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + fed_client->security_token = parse_token(c->resp.payload, + c->resp.payload_size); + flb_plg_info(ins, "security token = %s", fed_client->security_token); + + err = get_token_exp(fed_client->security_token, &fed_client->expire, ins); + if (err) { + flb_plg_error(ins, "token error = %s",err); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_free(fed_uri); + flb_sds_destroy(json); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + flb_plg_info(ins, "token expiration time = %ld", fed_client->expire); + flb_free(json); + flb_free(fed_uri); + flb_free(s_leaf_cert); + flb_free(s_pub_key); + flb_free(s_inter_cert); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return 0; + +} + +static int file_to_buffer(const char *path, + char **out_buf, size_t *out_size) +{ + int ret; + char *buf; + ssize_t bytes; + FILE *fp; + struct stat st; + + if (!(fp = fopen(path, "r"))) { + return -1; + } + + ret = stat(path, &st); + if (ret == -1) { + flb_errno(); + fclose(fp); + return -1; + } + + buf = flb_calloc(1, (st.st_size + 1)); + if (!buf) { + flb_errno(); + fclose(fp); + return -1; + } + + bytes = fread(buf, st.st_size, 1, fp); + if (bytes < 1) { + flb_free(buf); + fclose(fp); + return -1; + } + + fclose(fp); + + *out_buf = buf; + *out_size = st.st_size; + + return 0; +} + +int refresh_oke_workload_security_token(struct federation_client *fed_client, + struct flb_config *config, + struct flb_output_instance *ins, + struct flb_upstream *fed_u, + flb_sds_t oke_sa_ca_file, + flb_sds_t oke_sa_token_file, + flb_sds_t *key_id) +{ + char* tmp, *host; + const char* err = NULL; + char buf[1024*8] = {0}; + size_t o_len; + int port = 12250, ret; + struct flb_tls *tls; + struct flb_http_client *c; + struct flb_connection *u_conn; + flb_sds_t auth_header; + char *token = NULL; + size_t tk_size; + flb_sds_t json; + flb_sds_t uri; + size_t b_sent; + time_t now; + + if (fed_client && fed_client->expire) { + now = time(NULL); + if (fed_client->expire > now) { + return 0; + } + } + + if (fed_client) { + fed_client = flb_calloc(1, sizeof(struct federation_client)); + } + + /* + tmp = getenv("OCI_RESOURCE_PRINCIPAL_REGION"); + if (!tmp) { + flb_plg_error(ctx->ins, "Not a valid region"); + flb_sds_destroy(sa_cert_path); + return -1; + } + ctx->fed_client->region = flb_sds_create_len(tmp, strlen(tmp)); + */ + session_key_supplier(&fed_client->private_key, + &fed_client->public_key, + ins); + host = getenv("KUBERNETES_SERVICE_HOST"); + if (!host) { + flb_plg_error(ins, "Host not found"); + return -1; + } + if (!fed_u) { + tls = flb_tls_create(FLB_TLS_CLIENT_MODE, + 0, + 1, + NULL, + NULL, + oke_sa_ca_file, + NULL, + NULL, + NULL); + fed_u = flb_upstream_create(config, host, port, FLB_IO_TLS, tls); + } + + ret = file_to_buffer(oke_sa_token_file, &token, &tk_size); + if (ret != 0) { + flb_errno(); + flb_plg_error(ins, "failed to load kubernetes service account token"); + return -1; + } + + char *s_pub_key = sanitize_certificate_string(fed_client->public_key); + json = flb_sds_create_size(1024*4); + flb_sds_snprintf(&json, flb_sds_alloc(json), + OCI_OKE_PROXYMUX_PAYLOAD, s_pub_key); + uri = flb_sds_create_len("/resourcePrincipalSessionTokens", + sizeof("/resourcePrincipalSessionTokens") - 1); + + u_conn = flb_upstream_conn_get(fed_u); + if (!u_conn) { + flb_errno(); + flb_plg_error(ins, + "failed to establish connection with kubernetes upstream"); + return -1; + } + c = flb_http_client(u_conn, FLB_HTTP_POST, uri, json, flb_sds_len(json), NULL, 0, NULL, 0); + if (!c) { + flb_errno(); + flb_plg_error(ins, + "failed to create http client"); + flb_upstream_conn_release(u_conn); + return -1; + } + auth_header = flb_sds_create_size(1024*4); + ret = flb_sds_snprintf(&auth_header, flb_sds_alloc(auth_header), "Bearer %s", token); + flb_http_add_header(c, FLB_OCI_HEADER_AUTH, + sizeof(FLB_OCI_HEADER_AUTH) - 1, + auth_header, + ret); + flb_http_add_header(c, FLB_OCI_HEADER_USER_AGENT, + sizeof(FLB_OCI_HEADER_USER_AGENT) - 1, + "Fluent-Bit", 10); + flb_http_add_header(c, FLB_OCI_HEADER_CONTENT_TYPE, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE) - 1, + FLB_OCI_HEADER_CONTENT_TYPE_JSON, + sizeof(FLB_OCI_HEADER_CONTENT_TYPE_JSON) - 1); + flb_http_add_header(c, "Accept", 6, "*/*", 3); + ret = flb_http_do(c, &b_sent); + if (ret != 0) { + flb_plg_error(ins, "http do error"); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + if (c->resp.status != 200) { + flb_plg_info(ins, "request body = %s", json); + flb_plg_info(ins, "request header = %s", c->header_buf); + flb_plg_error(ins, + "HTTP Status = %d, payload = %s", + c->resp.status, c->resp.payload); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + + c->resp.payload++; + c->resp.payload[strlen(c->resp.payload) - 1] = '\0'; + flb_base64_decode((unsigned char*)buf, + sizeof(buf), + &o_len, + (unsigned char*) c->resp.payload, + strlen(c->resp.payload)); + *key_id = parse_token(buf, strlen(buf)); + err = get_token_exp(*key_id + 3, &fed_client->expire, ins); + + if (err != NULL) { + flb_plg_error(ins, + "failed to extract token expiration time"); + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + return -1; + } + flb_plg_info(ins, "token expiration time = %ld", fed_client->expire); + // decode jwt token stored in buf + // Make the request and fetch the security token + + flb_http_client_destroy(c); + flb_upstream_conn_release(u_conn); + + return 0; +} + From 580f7054b4ea04dcc485a2983ad02dcfacfbd747 Mon Sep 17 00:00:00 2001 From: adiforluls Date: Tue, 21 Nov 2023 11:21:28 +0530 Subject: [PATCH 06/10] remove cruft and update Signed-off-by: adiforluls --- plugins/out_oracle_log_analytics/oci_logan.h | 24 ------------------- .../out_oracle_log_analytics/oci_logan_conf.c | 3 ++- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/plugins/out_oracle_log_analytics/oci_logan.h b/plugins/out_oracle_log_analytics/oci_logan.h index 9f07d9c2694..618375dad55 100644 --- a/plugins/out_oracle_log_analytics/oci_logan.h +++ b/plugins/out_oracle_log_analytics/oci_logan.h @@ -176,30 +176,6 @@ #include #include -#include "oci_client.h" - -struct federation_client { - struct flb_upstream *u; - flb_sds_t region; - flb_sds_t tenancy_id; - struct cert_retriever *leaf_cert_ret; - struct cert_retriever *intermediate_cert_ret; - // session key supplier - flb_sds_t private_key; - flb_sds_t public_key; - flb_sds_t key_id; - flb_sds_t security_token; - time_t expire; - pthread_mutex_t lock; -}; - -struct cert_retriever { - struct flb_upstream *u; - flb_sds_t cert_pem; - X509 *cert; - flb_sds_t private_key_pem; -}; - struct metadata_obj { flb_sds_t key; flb_sds_t val; diff --git a/plugins/out_oracle_log_analytics/oci_logan_conf.c b/plugins/out_oracle_log_analytics/oci_logan_conf.c index 2da03e8b98a..860a972f146 100644 --- a/plugins/out_oracle_log_analytics/oci_logan_conf.c +++ b/plugins/out_oracle_log_analytics/oci_logan_conf.c @@ -297,7 +297,8 @@ struct flb_oci_logan *flb_oci_logan_conf_create(struct flb_output_instance *ins, } if (strcasecmp(ctx->auth_type, USER_PRINCIPAL) == 0) { - if (create_pk_context(ctx->key_file, NULL, ctx) < 0) { + if (create_pk_context(ctx->key_file, NULL, + ctx->ins, &ctx->private_key) < 0) { flb_plg_error(ctx->ins, "failed to create pk context"); flb_oci_logan_conf_destroy(ctx); return NULL; From bbd181cc0049d50cb84651ccae0af3f463ada915 Mon Sep 17 00:00:00 2001 From: adiforluls Date: Tue, 21 Nov 2023 11:23:33 +0530 Subject: [PATCH 07/10] remove cruft and update Signed-off-by: adiforluls --- plugins/out_oracle_log_analytics/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/out_oracle_log_analytics/CMakeLists.txt b/plugins/out_oracle_log_analytics/CMakeLists.txt index b582f06cb44..81f971a9501 100644 --- a/plugins/out_oracle_log_analytics/CMakeLists.txt +++ b/plugins/out_oracle_log_analytics/CMakeLists.txt @@ -1,7 +1,6 @@ set(src oci_logan.c oci_logan_conf.c - oci_client.c ) FLB_PLUGIN(out_oracle_log_analytics "${src}" "") From 384e3e6c2f907551c9e4dcd7265ca401852562fc Mon Sep 17 00:00:00 2001 From: adiforluls Date: Tue, 21 Nov 2023 11:41:18 +0530 Subject: [PATCH 08/10] update Signed-off-by: adiforluls --- include/fluent-bit/oracle/flb_oracle_client.h | 1 - src/oracle/CMakeLists.txt | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/oracle/CMakeLists.txt diff --git a/include/fluent-bit/oracle/flb_oracle_client.h b/include/fluent-bit/oracle/flb_oracle_client.h index 5ee9bc7f4e8..3e2287c104f 100644 --- a/include/fluent-bit/oracle/flb_oracle_client.h +++ b/include/fluent-bit/oracle/flb_oracle_client.h @@ -165,6 +165,5 @@ int refresh_oke_workload_security_token(struct federation_client *fed_client, flb_sds_t oke_sa_ca_file, flb_sds_t oke_sa_token_file, flb_sds_t *key_id); - #endif //FLUENT_BIT_INCLUDE_FLUENT_BIT_ORACLE_FLB_ORACLE_CLIENT_H_ diff --git a/src/oracle/CMakeLists.txt b/src/oracle/CMakeLists.txt new file mode 100644 index 00000000000..60a9cd1b50c --- /dev/null +++ b/src/oracle/CMakeLists.txt @@ -0,0 +1,11 @@ +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +set(src + "flb_oracle_client.c" + ) + +add_library(flb-oracle STATIC ${src}) +target_link_libraries(flb-oracle) \ No newline at end of file From 59e7659540bbf7a2f6c0e568abd033e9678f926c Mon Sep 17 00:00:00 2001 From: adiforluls Date: Wed, 22 Nov 2023 11:24:35 +0530 Subject: [PATCH 09/10] refactor code Signed-off-by: adiforluls --- include/fluent-bit/oracle/flb_oracle_client.h | 10 +++++++++- src/oracle/flb_oracle_client.c | 12 +++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/fluent-bit/oracle/flb_oracle_client.h b/include/fluent-bit/oracle/flb_oracle_client.h index 3e2287c104f..34aea148d28 100644 --- a/include/fluent-bit/oracle/flb_oracle_client.h +++ b/include/fluent-bit/oracle/flb_oracle_client.h @@ -62,6 +62,13 @@ FLB_OCI_HEADER_CONTENT_LENGTH "\"" #define FLB_OCI_SIGN_SIGNATURE "signature" +#define FLB_OCI_FED_SIGN_HEADERS "headers=\"" \ + FLB_OCI_HEADER_REQUEST_TARGET " " \ + FLB_OCI_HEADER_DATE " " \ + FLB_OCI_HEADER_X_CONTENT_SHA256 " " \ + FLB_OCI_HEADER_CONTENT_TYPE " " \ + FLB_OCI_HEADER_CONTENT_LENGTH "\"" + #define METADATA_HOST_BASE "169.254.169.254" #define GET_REGION_URL "/opc/v2/instance/region" #define GET_REGION_INFO_URL "/opc/v2/instance/regionInfo/" @@ -107,7 +114,8 @@ int load_oci_credentials(struct flb_output_instance *ins, flb_sds_t *key_file, flb_sds_t *key_fingerprint, flb_sds_t *region); flb_sds_t create_authorization_header_content(flb_sds_t key_id, - flb_sds_t signature); + flb_sds_t signature, + char* sign_header); flb_sds_t create_base64_sha256_signature(flb_sds_t private_key, flb_sds_t signing_string, struct flb_output_instance *ins); diff --git a/src/oracle/flb_oracle_client.c b/src/oracle/flb_oracle_client.c index ad17b56e7bd..405b5fb39bf 100644 --- a/src/oracle/flb_oracle_client.c +++ b/src/oracle/flb_oracle_client.c @@ -304,7 +304,8 @@ int load_oci_credentials(struct flb_output_instance *ins, * signature="signature" */ flb_sds_t create_authorization_header_content(flb_sds_t key_id, - flb_sds_t signature) + flb_sds_t signature, + char* sign_header) { flb_sds_t content; @@ -320,8 +321,8 @@ flb_sds_t create_authorization_header_content(flb_sds_t key_id, flb_sds_cat_safe(&content, FLB_OCI_SIGN_ALGORITHM, sizeof(FLB_OCI_SIGN_ALGORITHM) - 1); flb_sds_cat_safe(&content, ",", 1); - flb_sds_cat_safe(&content, FLB_OCI_SIGN_HEADERS, - sizeof(FLB_OCI_SIGN_HEADERS) - 1); + flb_sds_cat_safe(&content, sign_header, + sizeof(sign_header) - 1); flb_sds_cat_safe(&content, ",", 1); flb_sds_cat_safe(&content, FLB_OCI_SIGN_SIGNATURE, sizeof(FLB_OCI_SIGN_SIGNATURE) - 1); @@ -543,7 +544,8 @@ int build_federation_client_headers(struct flb_http_client *c, flb_sds_t private goto error_label; } - auth_header_str = create_fed_authorization_header_content(signature, key_id); + auth_header_str = create_authorization_header_content(signature, key_id, + FLB_OCI_FED_SIGN_HEADERS); if (!auth_header_str) { flb_plg_error(ins, "cannot compose authorization header"); goto error_label; @@ -722,7 +724,7 @@ int build_headers(struct flb_http_client *c, flb_sds_t private_key, goto error_label; } - auth_header_str = create_authorization_header_content(key_id, signature); + auth_header_str = create_authorization_header_content(key_id, signature, FLB_OCI_SIGN_HEADERS); if (!auth_header_str) { flb_plg_error(ins, "cannot compose authorization header"); goto error_label; From ab41d5ed832bcc9ac7b0bb1c80d8be9c6aab85c5 Mon Sep 17 00:00:00 2001 From: adiforluls Date: Thu, 30 Nov 2023 14:07:31 +0530 Subject: [PATCH 10/10] install openssl explicitly in ubuntu UT Signed-off-by: adiforluls --- .github/workflows/unit-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml index 282879c5f51..f8cfd110f61 100644 --- a/.github/workflows/unit-tests.yaml +++ b/.github/workflows/unit-tests.yaml @@ -52,7 +52,7 @@ jobs: - name: Setup environment run: | sudo apt-get update - sudo apt-get install -y gcc-7 g++-7 clang-6.0 libsystemd-dev gcovr libyaml-dev + sudo apt-get install -y gcc-7 g++-7 clang-6.0 libsystemd-dev gcovr libyaml-dev openssl sudo ln -s /usr/bin/llvm-symbolizer-6.0 /usr/bin/llvm-symbolizer || true - uses: actions/checkout@v4