diff --git a/README.md b/README.md index 9e6d32c..e515b4a 100644 --- a/README.md +++ b/README.md @@ -632,6 +632,24 @@ data: ``` +You can limit what k8s objects can be looked up using the templting functionality by passing the `--allow-label` flag, for example `--allow-label=logs.vmware.com/allow`. +You can also override what label to use on specific Namespaces by passing the `--allow-label-annotation` falg and then setting what label to use in that annotation on the Namespace, for example, `--allow-label-annotation=logs.vmware.com/allow-label` +And in the Namespace: + +```yaml +apiVersion: v1 +kind: Namespace +metadata: + name: my-namespace + annotations: + logs.vmware.com/allow-label: "logs.vmware.com/my_namespace" +spec: + finalizers: + - kubernetes +``` + +And the templated config in this Namespace will only be allowed to lookup resources labeled with `logs.vmware.com/my_namespace="true"` + ### Custom resource definition(CRD) support (since v1.13.0) Custom resources are introduced from v1.13.0 release onwards. It allows to have a dedicated resource for fluentd configurations, which enables to manage them in a more consistent way and move away from the generic ConfigMaps. diff --git a/config-reloader/config/config.go b/config-reloader/config/config.go index f8a3550..08d25d7 100644 --- a/config-reloader/config/config.go +++ b/config-reloader/config/config.go @@ -52,6 +52,8 @@ type Config struct { MetricsPort int AllowTagExpansion bool AdminNamespace string + AllowLabel string + AllowLabelAnnotation string // parsed or processed/cached fields level logrus.Level ParsedMetaValues map[string]string @@ -233,6 +235,9 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("default-configmap", "Read the configmap by this name if namespace is not annotated. Use empty string to suppress the default.").Default(defaultConfig.DefaultConfigmapName).StringVar(&cfg.DefaultConfigmapName) app.Flag("status-annotation", "Store configuration errors in this annotation, leave empty to turn off").Default(defaultConfig.AnnotStatus).StringVar(&cfg.AnnotStatus) + app.Flag("allow-label", "When set only objects with this label can be fetched using go templating").Default(defaultConfig.AllowLabel).StringVar(&cfg.AllowLabel) + app.Flag("allow-label-annotation", "Which annotation on the namespace stores the allow label?").Default(defaultConfig.AllowLabelAnnotation).StringVar(&cfg.AllowLabelAnnotation) + app.Flag("prometheus-enabled", "Prometheus metrics enabled (default: false)").BoolVar(&cfg.PrometheusEnabled) app.Flag("metrics-port", "Expose prometheus metrics on this port (also needs --prometheus-enabled)").Default(strconv.Itoa(defaultConfig.MetricsPort)).IntVar(&cfg.MetricsPort) diff --git a/config-reloader/datasource/kube_informer.go b/config-reloader/datasource/kube_informer.go index 81c4686..afe1f06 100644 --- a/config-reloader/datasource/kube_informer.go +++ b/config-reloader/datasource/kube_informer.go @@ -157,6 +157,15 @@ func (d *kubeInformerConnection) GetNamespaces(ctx context.Context) ([]*Namespac return nil, err } + if d.cfg.AllowLabel != "" { + template.SetAllowLabel(d.cfg.AllowLabel) + } + if d.cfg.AllowLabelAnnotation != "" { + if label := nsobj.GetAnnotations()[d.cfg.AllowLabelAnnotation]; label != "" { + template.SetAllowLabel(label) + } + } + configdata, err := d.kubeds.GetFluentdConfig(ctx, ns) if err != nil { return nil, err @@ -407,7 +416,7 @@ func (d *kubeInformerConnection) discoverFluentdConfigNamespaces() ([]string, er } nsList := make([]string, 0) for _, crd := range fcList { - nsList = append(nsList, crd.ObjectMeta.Namespace) + nsList = append(nsList, crd.Namespace) } logrus.Debugf("Returned these namespaces for fluentdconfig crds: %v", nsList) return nsList, nil diff --git a/config-reloader/template/template.go b/config-reloader/template/template.go index ddd51d5..ce1ea99 100644 --- a/config-reloader/template/template.go +++ b/config-reloader/template/template.go @@ -6,6 +6,7 @@ import ( "io" "os" "reflect" + "strconv" "strings" "text/template" @@ -17,7 +18,14 @@ import ( "sigs.k8s.io/yaml" ) -var k8sClient client.Reader +var ( + k8sClient client.Reader + allowLabel string +) + +func SetAllowLabel(label string) { + allowLabel = label +} // Render is a go template rendering function it includes all the sprig lib functions // as well as some extras like a k8sLookup function to get values from k8s objects @@ -119,6 +127,11 @@ func k8sLookup(kind, namespace, name string) (map[string]interface{}, error) { }, &u); err != nil { return nil, fmt.Errorf("failed to get: %w", err) } + if allowLabel != "" { + if allow, _ := strconv.ParseBool(u.GetLabels()[allowLabel]); !allow { + return nil, fmt.Errorf("object not allowed") + } + } return u.UnstructuredContent(), nil } ul := &unstructured.UnstructuredList{} @@ -133,6 +146,14 @@ func k8sLookup(kind, namespace, name string) (map[string]interface{}, error) { if err := k8sClient.List(context.Background(), ul, opts); err != nil { return nil, fmt.Errorf("failed to list: %w", err) } + if allowLabel != "" { + for _, o := range ul.Items { + if allow, _ := strconv.ParseBool(o.GetLabels()[allowLabel]); !allow { + return nil, fmt.Errorf("object not allowed") + } + + } + } return ul.UnstructuredContent(), nil }