2020-02-10 17:18:20 +00:00
|
|
|
package proxy
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
2020-06-12 04:50:59 +00:00
|
|
|
"github.com/rancher/apiserver/pkg/types"
|
2020-02-10 17:18:20 +00:00
|
|
|
"github.com/rancher/steve/pkg/accesscontrol"
|
|
|
|
"k8s.io/apiserver/pkg/endpoints/request"
|
|
|
|
)
|
|
|
|
|
2022-10-14 23:17:32 +00:00
|
|
|
// WatchRefresh implements types.Store with awareness of changes to the requester's access.
|
2020-02-10 17:18:20 +00:00
|
|
|
type WatchRefresh struct {
|
|
|
|
types.Store
|
|
|
|
asl accesscontrol.AccessSetLookup
|
|
|
|
}
|
|
|
|
|
2024-06-05 14:17:12 +00:00
|
|
|
// NewWatchRefresh returns a new store with awareness of changes to the requester's access.
|
|
|
|
func NewWatchRefresh(s types.Store, asl accesscontrol.AccessSetLookup) *WatchRefresh {
|
|
|
|
return &WatchRefresh{
|
|
|
|
Store: s,
|
|
|
|
asl: asl,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 23:17:32 +00:00
|
|
|
// Watch performs a watch request which halts if the user's access level changes.
|
2020-02-10 17:18:20 +00:00
|
|
|
func (w *WatchRefresh) Watch(apiOp *types.APIRequest, schema *types.APISchema, wr types.WatchRequest) (chan types.APIEvent, error) {
|
|
|
|
user, ok := request.UserFrom(apiOp.Context())
|
|
|
|
if !ok {
|
|
|
|
return w.Store.Watch(apiOp, schema, wr)
|
|
|
|
}
|
|
|
|
|
|
|
|
as := w.asl.AccessFor(user)
|
|
|
|
ctx, cancel := context.WithCancel(apiOp.Context())
|
|
|
|
apiOp = apiOp.WithContext(ctx)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
2021-08-09 23:47:09 +00:00
|
|
|
case <-time.After(2 * time.Second):
|
2020-02-10 17:18:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
newAs := w.asl.AccessFor(user)
|
|
|
|
if as.ID != newAs.ID {
|
|
|
|
// RBAC changed
|
|
|
|
cancel()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return w.Store.Watch(apiOp, schema, wr)
|
|
|
|
}
|