Return status.bearerToken, not status.value, from minted tokens
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful

ext.cattle.io token creation returns TWO fields: status.value (just the secret
fragment) and status.bearerToken (the full usable credential, formatted
ext/<name>:<secret>). The plugin was returning status.value, so every minted
credential and every rotated root token was non-functional (401 against
Rancher). Verified: bearerToken authenticates (HTTP 200), value alone does not.

- client.go: MintToken returns status.bearerToken, falling back to status.value
  only if a Rancher build omits it.
- Reflect bearerToken in the mock Rancher and unit-test fake; assert the minted
  token is the ext/ bearer form.
This commit is contained in:
Ben Vincent
2026-07-18 16:27:05 +10:00
parent 67989d9768
commit 22c036d930
3 changed files with 33 additions and 12 deletions
+8 -4
View File
@@ -31,7 +31,8 @@ type tokenSpec struct {
}
type tokenStatus struct {
Value string `json:"value,omitempty"`
BearerToken string `json:"bearerToken,omitempty"`
Value string `json:"value,omitempty"`
}
type token struct {
@@ -88,16 +89,19 @@ func (s *store) handle(w http.ResponseWriter, r *http.Request) {
if newName == "" {
newName = req.Metadata.GenerateName + randHex(4)
}
value := "token-" + newName + ":" + randHex(16)
// ext.cattle.io returns the usable credential in status.bearerToken,
// formatted "ext/<name>:<secret>"; status.value is only the secret.
secret := randHex(16)
bearer := "ext/" + newName + ":" + secret
t := &token{
APIVersion: "ext.cattle.io/v1",
Kind: "Token",
Metadata: tokenMeta{Name: newName},
Spec: req.Spec,
Status: tokenStatus{Value: value},
Status: tokenStatus{BearerToken: bearer, Value: secret},
}
s.tokens[newName] = t
s.valid[value] = newName
s.valid[bearer] = newName
writeJSON(w, http.StatusCreated, t)
case r.Method == http.MethodGet && name != "": // read
t, ok := s.tokens[name]