metricbeat/autodiscover/appender/kubernetes/token/token.go (102 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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.
package token
import (
"fmt"
"os"
"github.com/elastic/beats/v7/libbeat/autodiscover"
"github.com/elastic/beats/v7/libbeat/common/cfgwarn"
"github.com/elastic/beats/v7/libbeat/conditions"
"github.com/elastic/elastic-agent-autodiscover/bus"
conf "github.com/elastic/elastic-agent-libs/config"
"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent-libs/mapstr"
)
type tokenAppender struct {
TokenPath string
Condition conditions.Condition
logger *logp.Logger
}
// InitializeModule initializes this module.
func InitializeModule() {
err := autodiscover.Registry.AddAppender("kubernetes.token", NewTokenAppender)
if err != nil {
logp.Error(fmt.Errorf("could not add `kubernetes.token` appender"))
}
}
// NewTokenAppender creates a token appender that can append a bearer token required to authenticate with
// protected endpoints
func NewTokenAppender(cfg *conf.C, logger *logp.Logger) (autodiscover.Appender, error) {
cfgwarn.Deprecate("7.0.0", "token appender is deprecated in favor of bearer_token_file config parameter")
conf := defaultConfig()
err := cfg.Unpack(&conf)
if err != nil {
return nil, fmt.Errorf("unable to unpack config due to error: %v", err)
}
var cond conditions.Condition
if conf.ConditionConfig != nil {
// Attempt to create a condition. If fails then report error
cond, err = conditions.NewCondition(conf.ConditionConfig)
if err != nil {
return nil, fmt.Errorf("unable to create condition due to error: %v", err)
}
}
appender := tokenAppender{
TokenPath: conf.TokenPath,
Condition: cond,
logger: logger,
}
return &appender, nil
}
// Append picks up a token from a file and adds it to the headers.Authorization section of the metricbeat module
func (t *tokenAppender) Append(event bus.Event) {
cfgsRaw, ok := event["config"]
// There are no configs
if !ok {
return
}
cfgs, ok := cfgsRaw.([]*conf.C)
// Config key doesnt have an array of config objects
if !ok {
return
}
// Check if the condition is met. Attempt to append only if that is the case.
if t.Condition == nil || t.Condition.Check(mapstr.M(event)) == true {
tok := t.getAuthHeaderFromToken()
// If token is empty then just return
if tok == "" {
return
}
for i := 0; i < len(cfgs); i++ {
// Unpack the config
cfg := cfgs[i]
c := mapstr.M{}
err := cfg.Unpack(&c)
if err != nil {
t.logger.Named("kubernetes.config").Debugf("unable to unpack config due to error: %v", err)
continue
}
var headers mapstr.M
if hRaw, ok := c["headers"]; ok {
// If headers is not a map then continue to next config
if headers, ok = hRaw.(mapstr.M); !ok {
continue
}
} else {
headers = mapstr.M{}
}
// Assign authorization header and add it back to the config
headers["Authorization"] = tok
c["headers"] = headers
// Repack the configuration
newCfg, err := conf.NewConfigFrom(&c)
if err != nil {
t.logger.Named("kubernetes.config").Debugf("unable to repack config due to error: %v", err)
continue
}
cfgs[i] = newCfg
}
event["config"] = cfgs
}
}
func (t *tokenAppender) getAuthHeaderFromToken() string {
var token string
if t.TokenPath != "" {
b, err := os.ReadFile(t.TokenPath)
if err != nil {
t.logger.Errorf("Reading token file failed with err: %v", err)
}
if len(b) != 0 {
if b[len(b)-1] == '\n' {
b = b[0 : len(b)-1]
}
token = fmt.Sprintf("Bearer %s", string(b))
}
}
return token
}