Coverage Report

Created: 2026-11-12 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/plugins/out_chronicle/chronicle_conf.c
Line
Count
Source
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2026 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_output_plugin.h>
21
#include <fluent-bit/flb_unescape.h>
22
#include <fluent-bit/flb_jsmn.h>
23
#include <fluent-bit/flb_pack.h>
24
#include <fluent-bit/flb_utils.h>
25
#include <fluent-bit/flb_aws_credentials.h>
26
#include <fluent-bit/flb_slist.h>
27
28
#include <ctype.h>
29
#include <sys/types.h>
30
#include <sys/stat.h>
31
32
#include "chronicle.h"
33
#include "chronicle_conf.h"
34
35
36
0
static inline int key_cmp(char *str, int len, char *cmp) {
37
38
0
    if (strlen(cmp) != len) {
39
0
        return -1;
40
0
    }
41
42
0
    return strncasecmp(str, cmp, len);
43
0
}
44
45
static void chronicle_labels_destroy(struct flb_chronicle *ctx)
46
0
{
47
0
    struct mk_list *head;
48
0
    struct mk_list *tmp;
49
0
    struct flb_chronicle_label *label;
50
51
0
    mk_list_foreach_safe(head, tmp, &ctx->labels) {
52
0
        label = mk_list_entry(head, struct flb_chronicle_label, _head);
53
0
        mk_list_del(&label->_head);
54
55
0
        flb_sds_destroy(label->key);
56
0
        flb_sds_destroy(label->value);
57
58
0
        if (label->ra) {
59
0
            flb_ra_destroy(label->ra);
60
0
        }
61
62
0
        flb_free(label);
63
0
    }
64
0
}
65
66
static int chronicle_label_add(struct flb_chronicle *ctx,
67
                               char *key, size_t key_len,
68
                               char *value, size_t value_len)
69
0
{
70
0
    struct flb_chronicle_label *label;
71
72
0
    if (key == NULL || key_len == 0 || value == NULL) {
73
0
        flb_plg_error(ctx->ins, "label requires a non-empty key and value");
74
0
        return -1;
75
0
    }
76
77
0
    label = flb_calloc(1, sizeof(struct flb_chronicle_label));
78
0
    if (!label) {
79
0
        flb_errno();
80
0
        return -1;
81
0
    }
82
83
0
    label->key = flb_sds_create_len(key, key_len);
84
0
    if (!label->key) {
85
0
        flb_free(label);
86
0
        return -1;
87
0
    }
88
89
0
    label->value = flb_sds_create_len(value, value_len);
90
0
    if (!label->value) {
91
0
        flb_sds_destroy(label->key);
92
0
        flb_free(label);
93
0
        return -1;
94
0
    }
95
96
0
    if (memchr(value, '$', value_len) != NULL) {
97
0
        label->ra = flb_ra_create(label->value, FLB_FALSE);
98
0
        if (!label->ra) {
99
0
            flb_plg_error(ctx->ins, "invalid label record accessor '%s'",
100
0
                          label->value);
101
0
            flb_sds_destroy(label->key);
102
0
            flb_sds_destroy(label->value);
103
0
            flb_free(label);
104
0
            return -1;
105
0
        }
106
0
    }
107
108
0
    mk_list_add(&label->_head, &ctx->labels);
109
0
    return 0;
110
0
}
111
112
static int chronicle_label_exists(struct flb_chronicle *ctx, flb_sds_t key)
113
0
{
114
0
    struct mk_list *head;
115
0
    struct flb_chronicle_label *label;
116
117
0
    mk_list_foreach(head, &ctx->labels) {
118
0
        label = mk_list_entry(head, struct flb_chronicle_label, _head);
119
120
0
        if (flb_sds_len(label->key) == flb_sds_len(key) &&
121
0
            strncmp(label->key, key, flb_sds_len(key)) == 0) {
122
0
            return FLB_TRUE;
123
0
        }
124
0
    }
125
126
0
    return FLB_FALSE;
127
0
}
128
129
static int chronicle_configure_labels(struct flb_chronicle *ctx)
130
0
{
131
0
    int ret;
132
0
    struct mk_list *head;
133
0
    struct flb_config_map_val *mv;
134
0
    struct flb_slist_entry *key;
135
0
    struct flb_slist_entry *val;
136
137
0
    if (ctx->label_properties) {
138
0
        flb_config_map_foreach(head, mv, ctx->label_properties) {
139
0
            if (mk_list_size(mv->val.list) != 2) {
140
0
                flb_plg_error(ctx->ins, "'label' expects a key and a value");
141
0
                return -1;
142
0
            }
143
144
0
            key = mk_list_entry_first(mv->val.list,
145
0
                                      struct flb_slist_entry, _head);
146
0
            val = mk_list_entry_last(mv->val.list,
147
0
                                     struct flb_slist_entry, _head);
148
149
            /* The Chronicle API sends labels as a map keyed by label name */
150
0
            if (ctx->api == FLB_CHRONICLE_API_CHRONICLE &&
151
0
                chronicle_label_exists(ctx, key->str) == FLB_TRUE) {
152
0
                flb_plg_error(ctx->ins, "duplicate label '%s' is not supported "
153
0
                              "by the Chronicle API", key->str);
154
0
                return -1;
155
0
            }
156
157
0
            ret = chronicle_label_add(ctx,
158
0
                                      key->str, flb_sds_len(key->str),
159
0
                                      val->str, flb_sds_len(val->str));
160
0
            if (ret != 0) {
161
0
                return -1;
162
0
            }
163
0
        }
164
0
    }
165
166
0
    return 0;
167
0
}
168
169
static int flb_chronicle_read_credentials_file(struct flb_chronicle *ctx,
170
                                              char *creds,
171
                                              struct flb_chronicle_oauth_credentials *ctx_creds)
172
0
{
173
0
    int i;
174
0
    int ret;
175
0
    int len;
176
0
    int key_len;
177
0
    int val_len;
178
0
    int tok_size = 32;
179
0
    char *buf;
180
0
    char *key;
181
0
    char *val;
182
0
    flb_sds_t tmp;
183
0
    struct stat st;
184
0
    jsmn_parser parser;
185
0
    jsmntok_t *t;
186
0
    jsmntok_t *tokens;
187
188
    /* Validate credentials path */
189
0
    ret = stat(creds, &st);
190
0
    if (ret == -1) {
191
0
        flb_errno();
192
0
        flb_plg_error(ctx->ins, "cannot open credentials file: %s",
193
0
                      creds);
194
0
        return -1;
195
0
    }
196
197
0
    if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
198
0
        flb_plg_error(ctx->ins, "credentials file "
199
0
                      "is not a valid file: %s", creds);
200
0
        return -1;
201
0
    }
202
203
    /* Read file content */
204
0
    buf = mk_file_to_buffer(creds);
205
0
    if (!buf) {
206
0
        flb_plg_error(ctx->ins, "error reading credentials file: %s",
207
0
                      creds);
208
0
        return -1;
209
0
    }
210
211
    /* Parse content */
212
0
    jsmn_init(&parser);
213
0
    tokens = flb_calloc(1, sizeof(jsmntok_t) * tok_size);
214
0
    if (!tokens) {
215
0
        flb_errno();
216
0
        flb_free(buf);
217
0
        return -1;
218
0
    }
219
220
0
    ret = jsmn_parse(&parser, buf, st.st_size, tokens, tok_size);
221
0
    if (ret <= 0) {
222
0
        flb_plg_error(ctx->ins, "invalid JSON credentials file: %s",
223
0
                      creds);
224
0
        flb_free(buf);
225
0
        flb_free(tokens);
226
0
        return -1;
227
0
    }
228
229
0
    t = &tokens[0];
230
0
    if (t->type != JSMN_OBJECT) {
231
0
        flb_plg_error(ctx->ins, "invalid JSON map on file: %s",
232
0
                      creds);
233
0
        flb_free(buf);
234
0
        flb_free(tokens);
235
0
        return -1;
236
0
    }
237
238
    /* Parse JSON tokens */
239
0
    for (i = 1; i < ret; i++) {
240
0
        t = &tokens[i];
241
0
        if (t->type != JSMN_STRING) {
242
0
            continue;
243
0
        }
244
245
0
        if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)){
246
0
            break;
247
0
        }
248
249
        /* Key */
250
0
        key = buf + t->start;
251
0
        key_len = (t->end - t->start);
252
253
        /* Value */
254
0
        i++;
255
0
        t = &tokens[i];
256
0
        val = buf + t->start;
257
0
        val_len = (t->end - t->start);
258
259
0
        if (key_cmp(key, key_len, "type") == 0) {
260
0
            ctx_creds->type = flb_sds_create_len(val, val_len);
261
0
        }
262
0
        else if (key_cmp(key, key_len, "project_id") == 0) {
263
0
            ctx_creds->project_id = flb_sds_create_len(val, val_len);
264
0
        }
265
0
        else if (key_cmp(key, key_len, "private_key_id") == 0) {
266
0
            ctx_creds->private_key_id = flb_sds_create_len(val, val_len);
267
0
        }
268
0
        else if (key_cmp(key, key_len, "private_key") == 0) {
269
0
            tmp = flb_sds_create_len(val, val_len);
270
0
            if (tmp) {
271
                /* Unescape private key */
272
0
                len = flb_sds_len(tmp);
273
0
                ctx_creds->private_key = flb_sds_create_size(len);
274
0
                flb_unescape_string(tmp, len,
275
0
                                    &ctx_creds->private_key);
276
0
                flb_sds_destroy(tmp);
277
0
            }
278
0
        }
279
0
        else if (key_cmp(key, key_len, "client_email") == 0) {
280
0
            ctx_creds->client_email = flb_sds_create_len(val, val_len);
281
0
        }
282
0
        else if (key_cmp(key, key_len, "client_id") == 0) {
283
0
            ctx_creds->client_id = flb_sds_create_len(val, val_len);
284
0
        }
285
0
        else if (key_cmp(key, key_len, "auth_uri") == 0) {
286
0
            ctx_creds->auth_uri = flb_sds_create_len(val, val_len);
287
0
        }
288
0
        else if (key_cmp(key, key_len, "token_uri") == 0) {
289
0
            ctx_creds->token_uri = flb_sds_create_len(val, val_len);
290
0
        }
291
0
    }
292
293
0
    flb_free(buf);
294
0
    flb_free(tokens);
295
296
0
    return 0;
297
0
}
298
299
/* Check that a value can be used as-is as a segment of the request path */
300
static int chronicle_api_check_path_segment(struct flb_chronicle *ctx,
301
                                            const char *name, flb_sds_t value)
302
0
{
303
0
    size_t i;
304
0
    char c;
305
306
0
    if (flb_sds_len(value) == 0) {
307
0
        flb_plg_error(ctx->ins, "property '%s' cannot be empty", name);
308
0
        return -1;
309
0
    }
310
311
0
    for (i = 0; i < flb_sds_len(value); i++) {
312
0
        c = value[i];
313
0
        if (!isalnum((unsigned char) c) &&
314
0
            c != '-' && c != '.' && c != '_' && c != '~' && c != ':') {
315
0
            flb_plg_error(ctx->ins, "property '%s' has an invalid character: '%s'",
316
0
                          name, value);
317
0
            return -1;
318
0
        }
319
0
    }
320
321
0
    return 0;
322
0
}
323
324
/* Compose the base URI and the logs:import endpoint for the Chronicle API */
325
static int chronicle_api_configure(struct flb_chronicle *ctx)
326
0
{
327
0
    size_t i;
328
0
    char c;
329
0
    flb_sds_t tmp;
330
331
    /* The region is the location of the Google SecOps instance, e.g: 'us' */
332
0
    if (ctx->region == NULL) {
333
0
        ctx->location = flb_sds_create(FLB_CHRONICLE_API_DEFAULT_LOCATION);
334
0
    }
335
0
    else {
336
0
        ctx->location = flb_sds_create(ctx->region);
337
0
    }
338
0
    if (!ctx->location) {
339
0
        flb_errno();
340
0
        return -1;
341
0
    }
342
343
    /* The location is also part of the hostname */
344
0
    if (flb_sds_len(ctx->location) == 0) {
345
0
        flb_plg_error(ctx->ins, "property 'region' cannot be empty");
346
0
        return -1;
347
0
    }
348
349
0
    for (i = 0; i < flb_sds_len(ctx->location); i++) {
350
0
        c = tolower((unsigned char) ctx->location[i]);
351
0
        if (!isalnum((unsigned char) c) && c != '-') {
352
0
            flb_plg_error(ctx->ins, "invalid region '%s' for the Chronicle API",
353
0
                          ctx->region);
354
0
            return -1;
355
0
        }
356
0
        ctx->location[i] = c;
357
0
    }
358
359
0
    if (chronicle_api_check_path_segment(ctx, "project_id", ctx->project_id) != 0 ||
360
0
        chronicle_api_check_path_segment(ctx, "customer_id", ctx->customer_id) != 0 ||
361
0
        chronicle_api_check_path_segment(ctx, "log_type", ctx->log_type) != 0) {
362
0
        return -1;
363
0
    }
364
365
0
    ctx->uri = flb_sds_create_size(64);
366
0
    if (!ctx->uri) {
367
0
        flb_errno();
368
0
        return -1;
369
0
    }
370
371
0
    tmp = flb_sds_printf(&ctx->uri, FLB_CHRONICLE_API_URL_BASE, ctx->location);
372
0
    if (!tmp) {
373
0
        return -1;
374
0
    }
375
376
0
    ctx->endpoint = flb_sds_create_size(256);
377
0
    if (!ctx->endpoint) {
378
0
        flb_errno();
379
0
        return -1;
380
0
    }
381
382
0
    tmp = flb_sds_printf(&ctx->endpoint, FLB_CHRONICLE_API_IMPORT_ENDPOINT,
383
0
                         ctx->project_id, ctx->location,
384
0
                         ctx->customer_id, ctx->log_type);
385
0
    if (!tmp) {
386
0
        return -1;
387
0
    }
388
389
0
    ctx->max_payload_size = FLB_CHRONICLE_API_MAX_PAYLOAD_SIZE;
390
391
0
    return 0;
392
0
}
393
394
struct flb_chronicle *flb_chronicle_conf_create(struct flb_output_instance *ins,
395
                                              struct flb_config *config)
396
0
{
397
0
    int ret;
398
0
    const char *tmp;
399
0
    struct flb_chronicle *ctx;
400
0
    struct flb_chronicle_oauth_credentials *creds;
401
402
    /* Allocate config context */
403
0
    ctx = flb_calloc(1, sizeof(struct flb_chronicle));
404
0
    if (!ctx) {
405
0
        flb_errno();
406
0
        return NULL;
407
0
    }
408
0
    ctx->ins = ins;
409
0
    ctx->config = config;
410
0
    mk_list_init(&ctx->labels);
411
412
0
    ret = flb_output_config_map_set(ins, (void *)ctx);
413
0
    if (ret == -1) {
414
0
        flb_plg_error(ins, "unable to load configuration");
415
0
        flb_free(ctx);
416
0
        return NULL;
417
0
    }
418
419
    /* config: 'api' */
420
0
    if (strcasecmp(ctx->api_str, "legacy") == 0) {
421
0
        ctx->api = FLB_CHRONICLE_API_LEGACY;
422
0
    }
423
0
    else if (strcasecmp(ctx->api_str, "chronicle") == 0) {
424
0
        ctx->api = FLB_CHRONICLE_API_CHRONICLE;
425
0
    }
426
0
    else {
427
0
        flb_plg_error(ins, "invalid api '%s', expected 'legacy' or 'chronicle'",
428
0
                      ctx->api_str);
429
0
        flb_free(ctx);
430
0
        return NULL;
431
0
    }
432
433
    /* config: 'compress' */
434
0
    ctx->compress_gzip = FLB_FALSE;
435
0
    if (ctx->compress_str) {
436
0
        if (strcasecmp(ctx->compress_str, "gzip") == 0) {
437
0
            ctx->compress_gzip = FLB_TRUE;
438
0
        }
439
0
        else if (strcasecmp(ctx->compress_str, "none") != 0) {
440
0
            flb_plg_error(ins, "invalid compress '%s', expected 'gzip' or 'none'",
441
0
                          ctx->compress_str);
442
0
            flb_free(ctx);
443
0
            return NULL;
444
0
        }
445
0
    }
446
447
    /* Lookup credentials file */
448
0
    creds = flb_calloc(1, sizeof(struct flb_chronicle_oauth_credentials));
449
0
    if (!creds) {
450
0
        flb_errno();
451
0
        flb_free(ctx);
452
0
        return NULL;
453
0
    }
454
0
    ctx->oauth_credentials = creds;
455
456
0
    if (ctx->credentials_file == NULL) {
457
0
        tmp = getenv("GOOGLE_SERVICE_CREDENTIALS");
458
0
        if (tmp) {
459
0
            ctx->credentials_file = flb_sds_create(tmp);
460
0
        }
461
0
    }
462
463
0
    if (ins->test_mode == FLB_FALSE) {
464
0
        if (ctx->credentials_file) {
465
0
            ret = flb_chronicle_read_credentials_file(ctx,
466
0
                                                      ctx->credentials_file,
467
0
                                                      ctx->oauth_credentials);
468
0
            if (ret != 0) {
469
0
                flb_chronicle_conf_destroy(ctx);
470
0
                return NULL;
471
0
            }
472
0
        }
473
0
        else if (!ctx->credentials_file) {
474
            /*
475
             * If no credentials file has been defined, do manual lookup of the
476
             * client email and the private key.
477
             */
478
479
            /* Service Account Email */
480
0
            tmp = flb_output_get_property("service_account_email", ins);
481
0
            if (tmp) {
482
0
                creds->client_email = flb_sds_create(tmp);
483
0
            }
484
0
            else {
485
0
                tmp = getenv("SERVICE_ACCOUNT_EMAIL");
486
0
                if (tmp) {
487
0
                    creds->client_email = flb_sds_create(tmp);
488
0
                }
489
0
            }
490
491
            /* Service Account Secret */
492
0
            tmp = flb_output_get_property("service_account_secret", ins);
493
0
            if (tmp) {
494
0
                creds->private_key = flb_sds_create(tmp);
495
0
            }
496
0
            else {
497
0
                tmp = getenv("SERVICE_ACCOUNT_SECRET");
498
0
                if (tmp) {
499
0
                    creds->private_key = flb_sds_create(tmp);
500
0
                }
501
0
            }
502
503
0
            if (!creds->client_email) {
504
0
                flb_plg_error(ctx->ins, "service_account_email/client_email is not defined");
505
0
                flb_chronicle_conf_destroy(ctx);
506
0
                return NULL;
507
0
            }
508
509
0
            if (!creds->private_key) {
510
0
                flb_plg_error(ctx->ins, "service_account_secret/private_key is not defined");
511
0
                flb_chronicle_conf_destroy(ctx);
512
0
                return NULL;
513
0
            }
514
0
        }
515
0
    }
516
517
    /* config: 'project_id' */
518
0
    if (ctx->project_id == NULL) {
519
0
        if (creds->project_id) {
520
            /* flb_config_map_destroy uses the pointer within the config_map struct to
521
             * free the value so if we assign it here it is safe to free later with the
522
             * creds struct. If we do not we will leak here.
523
             */
524
0
            ctx->project_id = creds->project_id;
525
0
            if (!ctx->project_id) {
526
0
                flb_plg_error(ctx->ins,
527
0
                              "failed extracting 'project_id' from credentials.");
528
0
                flb_chronicle_conf_destroy(ctx);
529
0
                return NULL;
530
0
            }
531
0
        }
532
0
        else {
533
0
            flb_plg_error(ctx->ins,
534
0
                          "no 'project_id' configured or present in credentials.");
535
0
            flb_chronicle_conf_destroy(ctx);
536
0
            return NULL;
537
0
        }
538
0
    }
539
540
    /* config: 'customer_id' */
541
0
    if (ctx->customer_id == NULL) {
542
0
        flb_plg_error(ctx->ins, "property 'customer_id' is not defined");
543
0
        flb_chronicle_conf_destroy(ctx);
544
0
        return NULL;
545
0
    }
546
547
    /* config: 'log_type' */
548
0
    if (ctx->log_type == NULL) {
549
0
        flb_plg_error(ctx->ins, "property 'log_type' is not defined");
550
0
        flb_chronicle_conf_destroy(ctx);
551
0
        return NULL;
552
0
    }
553
554
0
    if (ctx->namespace && flb_sds_len(ctx->namespace) == 0) {
555
0
        flb_plg_error(ctx->ins, "property 'namespace' cannot be empty");
556
0
        flb_chronicle_conf_destroy(ctx);
557
0
        return NULL;
558
0
    }
559
560
0
    if (ctx->namespace_key) {
561
0
        ctx->namespace_ra = flb_ra_create(ctx->namespace_key, FLB_FALSE);
562
0
        if (!ctx->namespace_ra) {
563
0
            flb_plg_error(ctx->ins, "invalid namespace_key record accessor '%s'",
564
0
                          ctx->namespace_key);
565
0
            flb_chronicle_conf_destroy(ctx);
566
0
            return NULL;
567
0
        }
568
0
    }
569
570
0
    ret = chronicle_configure_labels(ctx);
571
0
    if (ret != 0) {
572
0
        flb_chronicle_conf_destroy(ctx);
573
0
        return NULL;
574
0
    }
575
576
    /* Date key */
577
0
    ctx->date_key = ctx->json_date_key;
578
0
    tmp = flb_output_get_property("json_date_key", ins);
579
0
    if (tmp) {
580
        /* Just check if we have to disable it */
581
0
        if (flb_utils_bool(tmp) == FLB_FALSE) {
582
0
            ctx->date_key = NULL;
583
0
        }
584
0
    }
585
586
    /* Date format for JSON output */
587
0
    ctx->json_date_format = FLB_PACK_JSON_DATE_ISO8601;
588
0
    tmp = flb_output_get_property("json_date_format", ins);
589
0
    if (tmp) {
590
0
        ret = flb_pack_to_json_date_type(tmp);
591
0
        if (ret == -1) {
592
0
            flb_plg_error(ctx->ins, "invalid json_date_format '%s'. ", tmp);
593
0
            return NULL;
594
0
        }
595
0
        else {
596
0
            ctx->json_date_format = ret;
597
0
        }
598
0
    }
599
600
0
    if (ctx->api == FLB_CHRONICLE_API_CHRONICLE) {
601
0
        ret = chronicle_api_configure(ctx);
602
0
        if (ret != 0) {
603
0
            flb_chronicle_conf_destroy(ctx);
604
0
            return NULL;
605
0
        }
606
607
0
        flb_plg_info(ctx->ins, "api='chronicle' project='%s' customer_id='%s' "
608
0
                     "location='%s'",
609
0
                     ctx->project_id, ctx->customer_id, ctx->location);
610
611
0
        return ctx;
612
0
    }
613
614
0
    ctx->max_payload_size = FLB_CHRONICLE_MAX_PAYLOAD_SIZE;
615
616
    /* Create the target endpoint URI */
617
0
    ctx->endpoint = flb_sds_create_size(sizeof(FLB_CHRONICLE_UNSTRUCTURED_ENDPOINT));
618
0
    if (!ctx->endpoint) {
619
0
        flb_errno();
620
0
        flb_chronicle_conf_destroy(ctx);
621
0
        return NULL;
622
0
    }
623
0
    ctx->endpoint = flb_sds_printf(&ctx->endpoint, FLB_CHRONICLE_UNSTRUCTURED_ENDPOINT);
624
625
    /* Create the base URI */
626
0
    if (ctx->region == NULL || strncasecmp(ctx->region, "US", 2) == 0) {
627
0
        ctx->uri = flb_sds_create_size(sizeof(FLB_CHRONICLE_URL_BASE));
628
0
        if (!ctx->uri) {
629
0
            flb_errno();
630
0
            flb_chronicle_conf_destroy(ctx);
631
0
            return NULL;
632
0
        }
633
0
        ctx->uri = flb_sds_printf(&ctx->uri, FLB_CHRONICLE_URL_BASE);
634
0
    }
635
0
    else if (strncasecmp(ctx->region, "EU", 2) == 0){
636
0
        ctx->uri = flb_sds_create_size(sizeof(FLB_CHRONICLE_URL_BASE_EU));
637
0
        if (!ctx->uri) {
638
0
            flb_errno();
639
0
            flb_chronicle_conf_destroy(ctx);
640
0
            return NULL;
641
0
        }
642
0
        ctx->uri = flb_sds_printf(&ctx->uri, FLB_CHRONICLE_URL_BASE_EU);
643
0
    }
644
0
    else if (strncasecmp(ctx->region, "UK", 2) == 0) {
645
0
        ctx->uri = flb_sds_create_size(sizeof(FLB_CHRONICLE_URL_BASE_UK));
646
0
        if (!ctx->uri) {
647
0
            flb_errno();
648
0
            flb_chronicle_conf_destroy(ctx);
649
0
            return NULL;
650
0
        }
651
0
        ctx->uri = flb_sds_printf(&ctx->uri, FLB_CHRONICLE_URL_BASE_UK);
652
0
    }
653
0
    else if (strncasecmp(ctx->region, "ASIA", 4) == 0) {
654
0
        ctx->uri = flb_sds_create_size(sizeof(FLB_CHRONICLE_URL_BASE_ASIA));
655
0
        if (!ctx->uri) {
656
0
            flb_errno();
657
0
            flb_chronicle_conf_destroy(ctx);
658
0
            return NULL;
659
0
        }
660
0
        ctx->uri = flb_sds_printf(&ctx->uri, FLB_CHRONICLE_URL_BASE_ASIA);
661
0
    }
662
0
    else {
663
0
        flb_plg_error(ctx->ins, "unsupported region");
664
0
        flb_chronicle_conf_destroy(ctx);
665
0
        return NULL;
666
0
    }
667
0
    flb_plg_info(ctx->ins, "project='%s' custumer_id='%s' region='%s'",
668
0
                 ctx->project_id, ctx->customer_id, ctx->region);
669
670
0
    return ctx;
671
0
}
672
673
674
int flb_chronicle_oauth_credentials_destroy(struct flb_chronicle_oauth_credentials *creds)
675
0
{
676
0
    if (!creds) {
677
0
        return -1;
678
0
    }
679
0
    flb_sds_destroy(creds->type);
680
0
    flb_sds_destroy(creds->project_id);
681
0
    flb_sds_destroy(creds->private_key_id);
682
0
    flb_sds_destroy(creds->private_key);
683
0
    flb_sds_destroy(creds->client_email);
684
0
    flb_sds_destroy(creds->client_id);
685
0
    flb_sds_destroy(creds->auth_uri);
686
0
    flb_sds_destroy(creds->token_uri);
687
688
0
    flb_free(creds);
689
690
0
    return 0;
691
0
}
692
693
int flb_chronicle_conf_destroy(struct flb_chronicle *ctx)
694
0
{
695
0
    if (!ctx) {
696
0
        return -1;
697
0
    }
698
699
0
    flb_chronicle_oauth_credentials_destroy(ctx->oauth_credentials);
700
701
0
    flb_sds_destroy(ctx->endpoint);
702
0
    flb_sds_destroy(ctx->uri);
703
0
    flb_sds_destroy(ctx->location);
704
705
0
    if (ctx->o) {
706
0
        flb_oauth2_destroy(ctx->o);
707
0
    }
708
709
0
    if (ctx->namespace_ra) {
710
0
        flb_ra_destroy(ctx->namespace_ra);
711
0
    }
712
713
0
    chronicle_labels_destroy(ctx);
714
715
0
    flb_free(ctx);
716
0
    return 0;
717
0
}