package auth import ( "context" "fmt" "github.com/hashicorp/vault/api" ) func init() { register(tokenMethod{}) } // tokenMethod is the trivial "I already have a token" method: it validates // the given token via lookup-self and returns a synthesized auth response so // the normal Result/token-storage pipeline works unchanged. This is what // backs `vault-tui login -method=token` and the VAULT_TOKEN/--token fast // path that internal/token.Resolve prefers over any interactive login. type tokenMethod struct{} func (tokenMethod) Name() string { return "token" } func (tokenMethod) DisplayName() string { return "Token" } func (tokenMethod) DefaultMount() string { return "token" } func (tokenMethod) Description() string { return "Use an existing Vault token (from VAULT_TOKEN, --token, or a saved token file)." } func (tokenMethod) Fields() []Field { return []Field{ {Name: "token", Label: "Token", Kind: FieldSecret, Required: true, EnvFallback: []string{"VAULT_TOKEN"}}, } } func (tokenMethod) Login(ctx context.Context, c *api.Client, req Request) (*api.Secret, error) { tok := req.Creds.Get("token") if tok == "" { return nil, fmt.Errorf("no token provided") } // lookup-self must run with the candidate token; c is otherwise // unauthenticated at this point (see internal/vault.NewClient's // ClearToken discipline), so this cannot affect any other caller. c.SetToken(tok) defer c.ClearToken() sec, err := c.Logical().ReadWithContext(ctx, "auth/token/lookup-self") if err != nil { return nil, fmt.Errorf("validating token: %w", err) } if sec == nil || sec.Data == nil { return nil, fmt.Errorf("token lookup returned no data") } renewable, _ := sec.TokenIsRenewable() ttl, _ := sec.TokenTTL() policies, _ := sec.TokenPolicies() return &api.Secret{ Auth: &api.SecretAuth{ ClientToken: tok, Renewable: renewable, LeaseDuration: int(ttl.Seconds()), Policies: policies, }, }, nil }