Remove legacy cross-namespace lease endpoints (#3152)

These endpoints were largely undocumented except for tests; rather than
continuing to support them, we should take the opportunity to simplify
the endpoint hierarchy to reduce noise in OpenAPI and similar places.

See also: CVE-2026-45808
Resolves: GHSA-v8v8-cm84-m686

Signed-off-by: Alexander Scheel <alex.scheel@control-plane.io>
This commit is contained in:
Alexander Scheel
2026-05-20 10:12:35 -05:00
committed by GitHub
parent 0d82e0a5a3
commit c0495646b4
14 changed files with 35 additions and 62 deletions
+1 -1
View File
@@ -256,7 +256,7 @@ func IsSudoPath(path string) bool {
}
// Some sudo paths have templated fields in them.
// (e.g. /sys/revoke-prefix/{prefix})
// (e.g. /sys/leases/revoke-prefix/{prefix})
// The values in the sudoPaths map are actually regular expressions,
// so we can check if our path matches against them.
for _, sudoPathRegexp := range sudoPaths {
+3
View File
@@ -0,0 +1,3 @@
```release-note:security
core: Remove legacy lease endpoints (`sys/revoke`, `sys/renew`, `sys/revoke-prefix`, and `sys/revoke-force`) due to cross-namespace lease modification. GHSA-v8v8-cm84-m686 / CVE-2026-45808.
```
+1 -1
View File
@@ -328,7 +328,7 @@ func Test(tt TestT, c TestCase) {
// Revoke this secret later
revoke = append(revoke, &logical.Request{
Operation: logical.UpdateOperation,
Path: "sys/revoke/" + resp.Secret.LeaseID,
Path: "sys/leases/revoke/" + resp.Secret.LeaseID,
})
}
+2 -10
View File
@@ -36,14 +36,6 @@ func TestSysRenew(t *testing.T) {
LeaseID string `json:"lease_id"`
Data map[string]interface{} `json:"data"`
}
resp = testHttpPut(t, token, addr+"/v1/sys/renew/"+result.LeaseID, nil)
testResponseStatus(t, resp, 200)
if err := jsonutil.DecodeJSONFromReader(resp.Body, &renewResult); err != nil {
t.Fatal(err)
}
if result.LeaseID != renewResult.LeaseID {
t.Fatal("lease id changed in renew request")
}
resp = testHttpPut(t, token, addr+"/v1/sys/leases/renew/"+result.LeaseID, nil)
testResponseStatus(t, resp, 200)
@@ -61,7 +53,7 @@ func TestSysRevoke(t *testing.T) {
defer ln.Close()
TestServerAuth(t, addr, token)
resp := testHttpPut(t, token, addr+"/v1/sys/revoke/secret/foo/1234", nil)
resp := testHttpPut(t, token, addr+"/v1/sys/leases/revoke/secret/foo/1234", nil)
testResponseStatus(t, resp, 204)
}
@@ -71,6 +63,6 @@ func TestSysRevokePrefix(t *testing.T) {
defer ln.Close()
TestServerAuth(t, addr, token)
resp := testHttpPut(t, token, addr+"/v1/sys/revoke-prefix/secret/foo/1234", nil)
resp := testHttpPut(t, token, addr+"/v1/sys/leases/revoke-prefix/secret/foo/1234", nil)
testResponseStatus(t, resp, 204)
}
+3 -3
View File
@@ -30,7 +30,7 @@ module('Unit | Serializer | policy', function (hooks) {
const POLICY_SHOW_RESPONSE = {
name: 'default',
rules:
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/leases/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
request_id: '890eabf8-d418-07af-f978-928d328a7e64',
lease_id: '',
renewable: false,
@@ -38,7 +38,7 @@ module('Unit | Serializer | policy', function (hooks) {
data: {
name: 'default',
rules:
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/leases/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
},
wrap_info: null,
warnings: null,
@@ -48,7 +48,7 @@ module('Unit | Serializer | policy', function (hooks) {
const EMBER_DATA_EXPECTS_FOR_POLICY_SHOW = {
name: 'default',
rules:
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
'\n# Allow tokens to look up their own properties\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\n# Allow tokens to renew themselves\npath "auth/token/renew-self" {\n capabilities = ["update"]\n}\n\n# Allow tokens to revoke themselves\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up its own capabilities on a path\npath "sys/capabilities-self" {\n capabilities = ["update"]\n}\n\n# Allow a token to renew a lease via lease_id in the request body\npath "sys/leases/renew" {\n capabilities = ["update"]\n}\n\n# Allow a token to manage its own cubbyhole\npath "cubbyhole/*" {\n capabilities = ["create", "read", "update", "delete", "list"]\n}\n\n# Allow a token to list its cubbyhole (not covered by the splat above)\npath "cubbyhole" {\n capabilities = ["list"]\n}\n\n# Allow a token to wrap arbitrary values in a response-wrapping token\npath "sys/wrapping/wrap" {\n capabilities = ["update"]\n}\n\n# Allow a token to look up the creation time and TTL of a given\n# response-wrapping token\npath "sys/wrapping/lookup" {\n capabilities = ["update"]\n}\n\n# Allow a token to unwrap a response-wrapping token. This is a convenience to\n# avoid client token swapping since this is also part of the response wrapping\n# policy.\npath "sys/wrapping/unwrap" {\n capabilities = ["update"]\n}\n',
};
test('it transforms a list request payload', function (assert) {
+1 -14
View File
@@ -2718,19 +2718,6 @@ func TestCore_RenewSameLease(t *testing.T) {
original := resp.Secret.LeaseID
// Renew the lease
req = logical.TestRequest(t, logical.UpdateOperation, "sys/renew/"+resp.Secret.LeaseID)
req.ClientToken = root
resp, err = c.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
t.Fatalf("err: %v", err)
}
// Verify the lease did not change
if resp.Secret.LeaseID != original {
t.Fatalf("lease id changed: %s %s", original, resp.Secret.LeaseID)
}
// Renew the lease (alternate path)
req = logical.TestRequest(t, logical.UpdateOperation, "sys/leases/renew/"+resp.Secret.LeaseID)
req.ClientToken = root
resp, err = c.HandleRequest(namespace.RootContext(t.Context()), req)
@@ -2775,7 +2762,7 @@ func TestCore_RenewToken_SingleRegister(t *testing.T) {
}
// Revoke using the renew prefix
req = logical.TestRequest(t, logical.UpdateOperation, "sys/revoke-prefix/auth/token/renew/")
req = logical.TestRequest(t, logical.UpdateOperation, "sys/leases/revoke-prefix/auth/token/renew/")
req.ClientToken = root
_, err = c.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
+4 -4
View File
@@ -2680,14 +2680,14 @@ func TestExpiration_RevokeForce(t *testing.T) {
}
req.Operation = logical.UpdateOperation
req.Path = "sys/revoke-prefix/badrenew/creds"
req.Path = "sys/leases/revoke-prefix/badrenew/creds"
_, err = core.HandleRequest(namespace.RootContext(t.Context()), req)
if err == nil {
t.Fatal("expected error")
}
req.Path = "sys/revoke-force/badrenew/creds"
req.Path = "sys/leases/revoke-force/badrenew/creds"
_, err = core.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
t.Fatalf("got error: %s", err)
@@ -2745,14 +2745,14 @@ func TestExpiration_RevokeForceSingle(t *testing.T) {
t.Fatalf("expected id %q, got %q", leaseID, resp.Data["id"].(string))
}
req.Path = "sys/revoke-prefix/" + leaseID
req.Path = "sys/leases/revoke-prefix/" + leaseID
_, err = core.HandleRequest(namespace.RootContext(t.Context()), req)
if err == nil {
t.Fatal("expected error")
}
req.Path = "sys/revoke-force/" + leaseID
req.Path = "sys/leases/revoke-force/" + leaseID
_, err = core.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
t.Fatalf("got error: %s", err)
-5
View File
@@ -96,11 +96,6 @@ func TestSystemBackend_InternalUIResultantACL(t *testing.T) {
"update",
},
},
"sys/renew": map[string]interface{}{
"capabilities": []interface{}{
"update",
},
},
"sys/tools/hash": map[string]interface{}{
"capabilities": []interface{}{
"update",
+4 -4
View File
@@ -2672,7 +2672,7 @@ func (b *SystemBackend) leasePaths() []*framework.Path {
},
{
Pattern: "(leases/)?renew" + framework.OptionalParamRegex("url_lease_id"),
Pattern: "leases/renew" + framework.OptionalParamRegex("url_lease_id"),
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "leases",
@@ -2712,7 +2712,7 @@ func (b *SystemBackend) leasePaths() []*framework.Path {
},
{
Pattern: "(leases/)?revoke" + framework.OptionalParamRegex("url_lease_id"),
Pattern: "leases/revoke" + framework.OptionalParamRegex("url_lease_id"),
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "leases",
@@ -2753,7 +2753,7 @@ func (b *SystemBackend) leasePaths() []*framework.Path {
},
{
Pattern: "(leases/)?revoke-force/(?P<prefix>.+)",
Pattern: "leases/revoke-force/(?P<prefix>.+)",
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "leases",
@@ -2786,7 +2786,7 @@ func (b *SystemBackend) leasePaths() []*framework.Path {
},
{
Pattern: "(leases/)?revoke-prefix/(?P<prefix>.+)",
Pattern: "leases/revoke-prefix/(?P<prefix>.+)",
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "leases",
+11 -11
View File
@@ -1554,7 +1554,7 @@ func TestSystemBackend_renew(t *testing.T) {
}
// Test orig path
req2 = logical.TestRequest(t, logical.UpdateOperation, "renew")
req2 = logical.TestRequest(t, logical.UpdateOperation, "leases/renew")
req2.Data["lease_id"] = resp.Secret.LeaseID
resp2, err = b.HandleRequest(namespace.RootContext(t.Context()), req2)
if err != nil {
@@ -1600,7 +1600,7 @@ func TestSystemBackend_renew_invalidID_origUrl(t *testing.T) {
b := testSystemBackend(t)
// Attempt renew
req := logical.TestRequest(t, logical.UpdateOperation, "renew/foobarbaz")
req := logical.TestRequest(t, logical.UpdateOperation, "leases/renew/foobarbaz")
resp, err := b.HandleRequest(namespace.RootContext(t.Context()), req)
if err != logical.ErrInvalidRequest {
t.Fatalf("err: %v", err)
@@ -1610,7 +1610,7 @@ func TestSystemBackend_renew_invalidID_origUrl(t *testing.T) {
}
// Attempt renew with other method
req = logical.TestRequest(t, logical.UpdateOperation, "renew")
req = logical.TestRequest(t, logical.UpdateOperation, "leases/renew")
req.Data["lease_id"] = "foobarbaz"
resp, err = b.HandleRequest(namespace.RootContext(t.Context()), req)
if err != logical.ErrInvalidRequest {
@@ -1653,7 +1653,7 @@ func TestSystemBackend_revoke(t *testing.T) {
}
// Attempt revoke
req2 := logical.TestRequest(t, logical.UpdateOperation, "revoke/"+resp.Secret.LeaseID)
req2 := logical.TestRequest(t, logical.UpdateOperation, "leases/revoke/"+resp.Secret.LeaseID)
resp2, err := b.HandleRequest(namespace.RootContext(t.Context()), req2)
if err != nil {
t.Fatalf("err: %v %#v", err, resp2)
@@ -1663,7 +1663,7 @@ func TestSystemBackend_revoke(t *testing.T) {
}
// Attempt renew
req3 := logical.TestRequest(t, logical.UpdateOperation, "renew/"+resp.Secret.LeaseID)
req3 := logical.TestRequest(t, logical.UpdateOperation, "leases/renew/"+resp.Secret.LeaseID)
resp3, err := b.HandleRequest(namespace.RootContext(t.Context()), req3)
if err != logical.ErrInvalidRequest {
t.Fatalf("err: %v", err)
@@ -1688,7 +1688,7 @@ func TestSystemBackend_revoke(t *testing.T) {
}
// Test the other route path
req2 = logical.TestRequest(t, logical.UpdateOperation, "revoke")
req2 = logical.TestRequest(t, logical.UpdateOperation, "leases/revoke")
req2.Data["lease_id"] = resp.Secret.LeaseID
resp2, err = b.HandleRequest(namespace.RootContext(t.Context()), req2)
if err != nil {
@@ -1763,7 +1763,7 @@ func TestSystemBackend_revoke_invalidID_origUrl(t *testing.T) {
b := testSystemBackend(t)
// Attempt revoke
req := logical.TestRequest(t, logical.UpdateOperation, "revoke/foobarbaz")
req := logical.TestRequest(t, logical.UpdateOperation, "leases/revoke/foobarbaz")
resp, err := b.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
t.Fatalf("err: %v", err)
@@ -1773,7 +1773,7 @@ func TestSystemBackend_revoke_invalidID_origUrl(t *testing.T) {
}
// Attempt revoke with other method
req = logical.TestRequest(t, logical.UpdateOperation, "revoke")
req = logical.TestRequest(t, logical.UpdateOperation, "leases/revoke")
req.Data["lease_id"] = "foobarbaz"
resp, err = b.HandleRequest(namespace.RootContext(t.Context()), req)
if err != nil {
@@ -1873,7 +1873,7 @@ func TestSystemBackend_revokePrefix_origUrl(t *testing.T) {
}
// Attempt revoke
req2 := logical.TestRequest(t, logical.UpdateOperation, "revoke-prefix/secret/")
req2 := logical.TestRequest(t, logical.UpdateOperation, "leases/revoke-prefix/secret/")
resp2, err := b.HandleRequest(namespace.RootContext(t.Context()), req2)
if err != nil {
t.Fatalf("err: %v %#v", err, resp2)
@@ -1883,7 +1883,7 @@ func TestSystemBackend_revokePrefix_origUrl(t *testing.T) {
}
// Attempt renew
req3 := logical.TestRequest(t, logical.UpdateOperation, "renew/"+resp.Secret.LeaseID)
req3 := logical.TestRequest(t, logical.UpdateOperation, "leases/renew/"+resp.Secret.LeaseID)
resp3, err := b.HandleRequest(namespace.RootContext(t.Context()), req3)
if err != logical.ErrInvalidRequest {
t.Fatalf("err: %v", err)
@@ -2008,7 +2008,7 @@ func TestSystemBackend_revokePrefixAuth_origUrl(t *testing.T) {
t.Fatalf("err: %v", err)
}
req := logical.TestRequest(t, logical.UpdateOperation, "revoke-prefix/auth/github/")
req := logical.TestRequest(t, logical.UpdateOperation, "leases/revoke-prefix/auth/github/")
resp, err := b.HandleRequest(ctx, req)
if err != nil {
t.Fatalf("err: %v %v", err, resp)
-3
View File
@@ -90,9 +90,6 @@ path "sys/internal/ui/resultant-acl" {
# Allow a token to renew a lease via lease_id in the request body; old path for
# old clients, new path for newer
path "sys/renew" {
capabilities = ["update"]
}
path "sys/leases/renew" {
capabilities = ["update"]
}
+1 -2
View File
@@ -1290,8 +1290,7 @@ func (c *Core) handleRequest(ctx context.Context, req *logical.Request) (retResp
// If there is a secret, we must register it with the expiration manager.
// We exclude renewal of a lease, since it does not need to be re-registered
if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/renew") &&
!strings.HasPrefix(req.Path, "sys/leases/renew") {
if resp != nil && resp.Secret != nil && !strings.HasPrefix(req.Path, "sys/leases/renew") {
// KV mounts should return the TTL but not register
// for a lease as this provides a massive slowdown
registerLease := true
+3 -3
View File
@@ -3192,14 +3192,14 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
}
// handleRevokeSelf handles the auth/token/revoke-self path for revocation of tokens
// in a way that revokes all child tokens. Normally, using sys/revoke/leaseID will revoke
// in a way that revokes all child tokens. Normally, using sys/leases/revoke/leaseID will revoke
// the token and all children anyways, but that is only available when there is a lease.
func (ts *TokenStore) handleRevokeSelf(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
return ts.revokeCommon(ctx, req, data, req.ClientToken)
}
// handleRevokeTree handles the auth/token/revoke/id path for revocation of tokens
// in a way that revokes all child tokens. Normally, using sys/revoke/leaseID will revoke
// in a way that revokes all child tokens. Normally, using sys/leases/revoke/leaseID will revoke
// the token and all children anyways, but that is only available when there is a lease.
func (ts *TokenStore) handleRevokeTree(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
id := data.Get("token").(string)
@@ -3250,7 +3250,7 @@ func (ts *TokenStore) revokeCommon(ctx context.Context, req *logical.Request, da
}
// handleRevokeOrphan handles the auth/token/revoke-orphan/id path for revocation of tokens
// in a way that leaves child tokens orphaned. Normally, using sys/revoke/leaseID will revoke
// in a way that leaves child tokens orphaned. Normally, using sys/leases/revoke/leaseID will revoke
// the token and all children.
func (ts *TokenStore) handleRevokeOrphan(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
// Parse the id
+1 -1
View File
@@ -27,7 +27,7 @@ Each token maintains the source path, or the login path, that was used
to create the token. This is used to allow source based revocation. For example,
if we believe our GitHub organization was compromised, we may want to revoke
all tokens generated via `auth/github/login`. This would be done by using the
`sys/revoke-prefix/` API with the `auth/github/` prefix. Revoking the
`sys/leases/revoke-prefix/` API with the `auth/github/` prefix. Revoking the
prefix will revoke all client tokens generated at that path, as well as all
dynamic secrets generated by those tokens. This provides a powerful "break glass"
procedure during a potential compromise.