// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package token_file import ( "context" "errors" "fmt" "net/http" "os" "strings" "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/command/agentproxyshared/auth" ) type tokenFileMethod struct { logger hclog.Logger mountPath string cachedToken string tokenFilePath string } func NewTokenFileAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) { if conf == nil { return nil, errors.New("empty config") } if conf.Config == nil { return nil, errors.New("empty config data") } a := &tokenFileMethod{ logger: conf.Logger, mountPath: "auth/token", } tokenFilePathRaw, ok := conf.Config["token_file_path"] if !ok { return nil, errors.New("missing 'token_file_path' value") } a.tokenFilePath, ok = tokenFilePathRaw.(string) if !ok { return nil, errors.New("could not convert 'token_file_path' config value to string") } if a.tokenFilePath == "" { return nil, errors.New("'token_file_path' value is empty") } return a, nil } func (a *tokenFileMethod) Authenticate(ctx context.Context, client *api.Client) (string, http.Header, map[string]interface{}, error) { token, err := os.ReadFile(a.tokenFilePath) if err != nil { if a.cachedToken == "" { return "", nil, nil, fmt.Errorf("error reading token file and no cached token known: %w", err) } a.logger.Warn("error reading token file", "error", err) } if len(token) == 0 { if a.cachedToken == "" { return "", nil, nil, errors.New("token file empty and no cached token known") } a.logger.Warn("token file exists but read empty value, re-using cached value") } else { a.cachedToken = strings.TrimSpace(string(token)) } // i.e. auth/token/lookup-self return fmt.Sprintf("%s/lookup-self", a.mountPath), nil, map[string]interface{}{ "token": a.cachedToken, }, nil } func (a *tokenFileMethod) NewCreds() chan struct{} { return nil } func (a *tokenFileMethod) CredSuccess() { } func (a *tokenFileMethod) Shutdown() { }