Skip to content

Commit 85866b1

Browse files
authored
Implement HTTPS pod to service association endpoint calls with mtls (fluent#16)
1 parent c11c024 commit 85866b1

File tree

7 files changed

+126
-12
lines changed

7 files changed

+126
-12
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
*~
55
_book/
66
lib/jemalloc
7+
cmake-build-debug/
78
tests/internal/flb_tests_internal.h
89
tests/runtime/flb_tests_runtime.h
10+
tests/internal/cmake-build-debug/
11+
tests/runtime/cmake-build-debug/
912
build/*
1013
include/fluent-bit/flb_info.h
1114
include/fluent-bit/flb_plugins.h

plugins/filter_kubernetes/kube_conf.c

+8
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,14 @@ void flb_kube_conf_destroy(struct flb_kube *ctx)
235235
flb_upstream_destroy(ctx->upstream);
236236
}
237237

238+
if(ctx->pod_association_tls) {
239+
flb_tls_destroy(ctx->pod_association_tls);
240+
}
241+
242+
if (ctx->pod_association_upstream) {
243+
flb_upstream_destroy(ctx->pod_association_upstream);
244+
}
245+
238246
#ifdef FLB_HAVE_TLS
239247
if (ctx->tls) {
240248
flb_tls_destroy(ctx->tls);

plugins/filter_kubernetes/kube_conf.h

+9
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ struct flb_kube {
192192
int pod_service_map_ttl;
193193
int pod_service_map_refresh_interval;
194194
flb_sds_t pod_service_preload_cache_dir;
195+
struct flb_upstream *pod_association_upstream;
196+
197+
//Agent TLS certs
198+
struct flb_tls *pod_association_tls;
199+
char *pod_association_host_server_ca_file;
200+
char *pod_association_host_client_cert_file;
201+
char *pod_association_host_client_key_file;
202+
int pod_association_host_tls_debug;
203+
int pod_association_host_tls_verify;
195204

196205
struct flb_tls *tls;
197206

plugins/filter_kubernetes/kube_meta.c

+32
Original file line numberDiff line numberDiff line change
@@ -1580,11 +1580,38 @@ static int wait_for_dns(struct flb_kube *ctx)
15801580
return -1;
15811581
}
15821582

1583+
int flb_kube_pod_association_init(struct flb_kube *ctx, struct flb_config *config) {
1584+
ctx->pod_association_tls = flb_tls_create(ctx->pod_association_host_tls_verify,
1585+
ctx->pod_association_host_tls_debug,
1586+
NULL, NULL,
1587+
ctx->pod_association_host_server_ca_file,
1588+
ctx->pod_association_host_client_cert_file, ctx->pod_association_host_client_key_file, NULL);
1589+
if (!ctx->pod_association_tls) {
1590+
flb_plg_error(ctx->ins, "[kube_meta] could not create TLS config for pod association host");
1591+
return -1;
1592+
}
1593+
ctx->pod_association_upstream = flb_upstream_create(config,
1594+
ctx->pod_association_host,
1595+
ctx->pod_association_port,
1596+
FLB_IO_TLS, ctx->pod_association_tls);
1597+
if (!ctx->pod_association_upstream) {
1598+
flb_plg_error(ctx->ins, "kube network init create pod association upstream failed");
1599+
flb_tls_destroy(ctx->pod_association_tls);
1600+
ctx->pod_association_tls = NULL;
1601+
return -1;
1602+
}
1603+
flb_upstream_thread_safe(ctx->pod_association_upstream);
1604+
mk_list_init(&ctx->pod_association_upstream->_head);
1605+
return 0;
1606+
}
1607+
15831608
static int flb_kube_network_init(struct flb_kube *ctx, struct flb_config *config)
15841609
{
15851610
int io_type = FLB_IO_TCP;
15861611

15871612
ctx->upstream = NULL;
1613+
ctx->pod_association_upstream = NULL;
1614+
ctx->pod_association_tls = NULL;
15881615

15891616
if (ctx->api_https == FLB_TRUE) {
15901617
if (!ctx->tls_ca_path && !ctx->tls_ca_file) {
@@ -1618,6 +1645,11 @@ static int flb_kube_network_init(struct flb_kube *ctx, struct flb_config *config
16181645
/* Remove async flag from upstream */
16191646
ctx->upstream->flags &= ~(FLB_IO_ASYNC);
16201647

1648+
/* Continue the filter kubernetes plugin functionality if the pod_association fails */
1649+
if(ctx->use_pod_association) {
1650+
flb_kube_pod_association_init(ctx, config);
1651+
}
1652+
16211653
return 0;
16221654
}
16231655

plugins/filter_kubernetes/kube_meta.h

+1
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ int flb_kube_meta_get(struct flb_kube *ctx,
6969
struct flb_kube_meta *meta,
7070
struct flb_kube_props *props);
7171
int flb_kube_meta_release(struct flb_kube_meta *meta);
72+
int flb_kube_pod_association_init(struct flb_kube *ctx, struct flb_config *config);
7273

7374
#endif

plugins/filter_kubernetes/kubernetes.c

+51-12
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ static int fetch_pod_service_map(struct flb_kube *ctx, char *api_server_url) {
191191
struct flb_http_client *c;
192192
size_t b_sent;
193193
struct flb_upstream_conn *u_conn;
194-
struct flb_upstream *u;
195194
char *buffer = {0};
196195

197196
flb_plg_debug(ctx->ins, "fetch pod to service map");
@@ -203,15 +202,25 @@ static int fetch_pod_service_map(struct flb_kube *ctx, char *api_server_url) {
203202
}
204203
else {
205204
/* Get upstream context and connection */
206-
u = flb_upstream_create(ctx->config,
207-
ctx->pod_association_host,
208-
ctx->pod_association_port,
209-
FLB_IO_TCP, NULL);
210-
u_conn = flb_upstream_conn_get(u);
205+
/* if block handles the TLS certificates update, as the Fluent-bit connection gets net timeout error, it destroys the upstream
206+
* On the next call to fetch_pod_service_map, it creates a new pod association upstream with latest TLS certs */
207+
if (!ctx->pod_association_upstream) {
208+
flb_plg_debug(ctx->ins, "[kubernetes] upstream object for pod association is NULL. Making a new one now");
209+
ret = flb_kube_pod_association_init(ctx,ctx->config);
210+
if( ret == -1) {
211+
return -1;
212+
}
213+
}
214+
215+
u_conn = flb_upstream_conn_get(ctx->pod_association_upstream);
211216
if (!u_conn) {
212-
flb_plg_error(ctx->ins, "no upstream connections available to %s:%i",
213-
u->tcp_host, u->tcp_port);
214-
return FLB_RETRY;
217+
flb_plg_error(ctx->ins, "[kubernetes] no upstream connections available to %s:%i",
218+
ctx->pod_association_upstream->tcp_host, ctx->pod_association_upstream->tcp_port);
219+
flb_upstream_destroy(ctx->pod_association_upstream);
220+
flb_tls_destroy(ctx->pod_association_tls);
221+
ctx->pod_association_upstream = NULL;
222+
ctx->pod_association_tls = NULL;
223+
return -1;
215224
}
216225

217226
/* Create HTTP client */
@@ -221,7 +230,12 @@ static int fetch_pod_service_map(struct flb_kube *ctx, char *api_server_url) {
221230
ctx->pod_association_port, NULL, 0);
222231

223232
if (!c) {
224-
flb_error("[kube_meta] could not create HTTP client");
233+
flb_error("[kubernetes] could not create HTTP client");
234+
flb_upstream_conn_release(u_conn);
235+
flb_upstream_destroy(ctx->pod_association_upstream);
236+
flb_tls_destroy(ctx->pod_association_tls);
237+
ctx->pod_association_upstream = NULL;
238+
ctx->pod_association_tls = NULL;
225239
return -1;
226240
}
227241

@@ -1159,7 +1173,7 @@ static struct flb_config_map config_map[] = {
11591173
* Will only check when "use_pod_association" config is set to true
11601174
*/
11611175
{
1162-
FLB_CONFIG_MAP_STR, "pod_association_host", "127.0.0.1",
1176+
FLB_CONFIG_MAP_STR, "pod_association_host", "cloudwatch-agent.amazon-cloudwatch",
11631177
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host),
11641178
"host to connect with when performing pod to service name association"
11651179
},
@@ -1202,7 +1216,32 @@ static struct flb_config_map config_map[] = {
12021216
0, FLB_TRUE, offsetof(struct flb_kube, pod_service_preload_cache_dir),
12031217
"set directory with pod to service map files"
12041218
},
1205-
1219+
{
1220+
FLB_CONFIG_MAP_STR, "pod_association_host_server_ca_file", "/etc/amazon-cloudwatch-observability-agent-server-cert/tls-ca.crt",
1221+
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host_server_ca_file),
1222+
"TLS CA certificate path for communication with agent server"
1223+
},
1224+
{
1225+
FLB_CONFIG_MAP_STR, "pod_association_host_client_cert_file", "/etc/amazon-cloudwatch-observability-agent-client-cert/client.crt",
1226+
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host_client_cert_file),
1227+
"Client Certificate path for enabling mTLS on calls to agent server"
1228+
},
1229+
{
1230+
FLB_CONFIG_MAP_STR, "pod_association_host_client_key_file", "/etc/amazon-cloudwatch-observability-agent-client-cert/client.key",
1231+
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host_client_key_file),
1232+
"Client Certificate Key path for enabling mTLS on calls to agent server"
1233+
},
1234+
{
1235+
FLB_CONFIG_MAP_INT, "pod_association_host_tls_debug", "0",
1236+
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host_tls_debug),
1237+
"set TLS debug level: 0 (no debug), 1 (error), "
1238+
"2 (state change), 3 (info) and 4 (verbose)"
1239+
},
1240+
{
1241+
FLB_CONFIG_MAP_BOOL, "pod_association_host_tls_verify", "true",
1242+
0, FLB_TRUE, offsetof(struct flb_kube, pod_association_host_tls_verify),
1243+
"enable or disable verification of TLS peer certificate"
1244+
},
12061245
/* EOF */
12071246
{0}
12081247
};

tests/runtime/filter_kubernetes.c

+22
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,25 @@ static void kube_test(const char *target, int type, const char *suffix, int nExp
354354
clear_file(path);
355355
}
356356

357+
//Testing the default values setup
358+
struct mk_list *head;
359+
struct flb_filter_instance *f_ins;
360+
mk_list_foreach(head, &ctx.flb->config->filters) {
361+
f_ins = mk_list_entry(head, struct flb_filter_instance, _head);
362+
if (strstr(f_ins->p->name, "kubernetes")) {
363+
TEST_CHECK(strcmp(f_ins->p->config_map[39].name, "pod_association_host_server_ca_file") == 0);
364+
TEST_CHECK(strcmp(f_ins->p->config_map[39].def_value, "/etc/amazon-cloudwatch-observability-agent-server-cert/tls-ca.crt") == 0);
365+
TEST_CHECK(strcmp(f_ins->p->config_map[40].name, "pod_association_host_client_cert_file") == 0);
366+
TEST_CHECK(strcmp(f_ins->p->config_map[40].def_value, "/etc/amazon-cloudwatch-observability-agent-client-cert/client.crt") == 0);
367+
TEST_CHECK(strcmp(f_ins->p->config_map[41].name, "pod_association_host_client_key_file") == 0);
368+
TEST_CHECK(strcmp(f_ins->p->config_map[41].def_value, "/etc/amazon-cloudwatch-observability-agent-client-cert/client.key") == 0);
369+
TEST_CHECK(strcmp(f_ins->p->config_map[42].name, "pod_association_host_tls_debug") == 0);
370+
TEST_CHECK(strcmp(f_ins->p->config_map[42].def_value, "0") == 0);
371+
TEST_CHECK(strcmp(f_ins->p->config_map[43].name, "pod_association_host_tls_verify") == 0);
372+
TEST_CHECK(strcmp(f_ins->p->config_map[43].def_value, "true") == 0);
373+
}
374+
}
375+
357376
/* Start the engine */
358377
ret = flb_start(ctx.flb);
359378
TEST_CHECK_(ret == 0, "starting engine");
@@ -951,6 +970,9 @@ static void flb_test_annotations_exclude_multiple_4_container_4_stderr()
951970
"use_kubelet", "true", \
952971
"kubelet_port", "8002", \
953972
"Pod_Service_Preload_Cache_Dir", DPATH "/servicemap", \
973+
"pod_association_host_server_ca_file", "/tst/ca.crt", \
974+
"pod_association_host_client_cert_file", "/tst/client.crt", \
975+
"pod_association_host_client_key_file", "/tst/client.key", \
954976
NULL); \
955977

956978
static void kube_options_use_pod_association_enabled()

0 commit comments

Comments
 (0)