mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-29 18:19:07 +02:00
[management] Add a revocation guard hook to the proxy token API (#7732)
Let an embedding binary refuse DELETE /api/reverse-proxies/proxy-tokens/{id}
through an optional proxytoken.RevocationGuard passed to NewAPIHandler.
It is checked after the ownership check, so another account's token
still returns 404 without reaching the guard, and before the token is
revoked. A status error from the guard is written with util.WriteError;
any other error becomes a generic 500.
Nothing installs a guard here, so OSS behavior is unchanged.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package proxytoken
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -18,13 +19,29 @@ import (
|
||||
"github.com/netbirdio/netbird/shared/management/status"
|
||||
)
|
||||
|
||||
// RevocationGuard vetoes the tenant-facing revocation of a proxy access
|
||||
// token. Implementations are supplied by integrations; none is installed by
|
||||
// default, so every token the caller's account owns may be revoked. It is
|
||||
// consulted after the ownership check and before the token is revoked. A
|
||||
// returned status error is written with util.WriteError: its type selects the
|
||||
// HTTP status and its message is shown to the caller, so it must not carry
|
||||
// internal detail. Any other error is reported as a generic internal error.
|
||||
type RevocationGuard interface {
|
||||
CheckProxyAccessTokenRevocation(ctx context.Context, token *types.ProxyAccessToken) error
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
store store.Store
|
||||
permissionsManager permissions.Manager
|
||||
// revocationGuard vetoes revocations. Optional — when nil every owned
|
||||
// token may be revoked.
|
||||
revocationGuard RevocationGuard
|
||||
}
|
||||
|
||||
func RegisterEndpoints(s store.Store, permissionsManager permissions.Manager, router *mux.Router) {
|
||||
h := &handler{store: s, permissionsManager: permissionsManager}
|
||||
// RegisterEndpoints registers the proxy token endpoints. revocationGuard is
|
||||
// optional; pass nil for no revocation policy.
|
||||
func RegisterEndpoints(s store.Store, permissionsManager permissions.Manager, revocationGuard RevocationGuard, router *mux.Router) {
|
||||
h := &handler{store: s, permissionsManager: permissionsManager, revocationGuard: revocationGuard}
|
||||
router.HandleFunc("/reverse-proxies/proxy-tokens", h.listTokens).Methods("GET", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies/proxy-tokens", h.createToken).Methods("POST", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies/proxy-tokens/{tokenId}", h.revokeToken).Methods("DELETE", "OPTIONS")
|
||||
@@ -154,6 +171,13 @@ func (h *handler) revokeToken(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.revocationGuard != nil {
|
||||
if err := h.revocationGuard.CheckProxyAccessTokenRevocation(ctx, token); err != nil {
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := h.store.RevokeProxyAccessToken(ctx, tokenID); err != nil {
|
||||
util.WriteErrorResponse("failed to revoke token", http.StatusInternalServerError, w)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user