@@ -57,30 +57,68 @@ type Warrant struct {
5757type appliesToUserFunc func (user user.Info , subject rbacv1.Subject , namespace string ) bool
5858type appliesToUserFuncCtx func (ctx context.Context , user user.Info , subject rbacv1.Subject , namespace string ) bool
5959
60+ var appliesToUserWithScopedAndWarrants = withScopesAndWarrants (appliesToUser )
61+
62+ // withScopesAndWarrants flattens the warrants, applies scopes and then applies the users to the subjects.
63+ func withScopesAndWarrants (appliesToUser appliesToUserFunc ) appliesToUserFuncCtx {
64+ return func (ctx context.Context , u user.Info , bindingSubject rbacv1.Subject , namespace string ) bool {
65+ var clusterName logicalcluster.Name
66+ if cluster := genericapirequest .ClusterFrom (ctx ); cluster != nil {
67+ clusterName = cluster .Name
68+ }
69+
70+ for _ , eu := range EffectiveUsers (clusterName , u ) {
71+ if appliesToUser (eu , bindingSubject , namespace ) {
72+ return true
73+ }
74+ }
75+
76+ return false
77+ }
78+ }
79+
6080var (
61- appliesToUserWithScopes = withScopes ( appliesToUser )
62- appliesToUserWithScopedAndWarrants = withWarrants ( appliesToUserWithScopes )
81+ authenticated = & user. DefaultInfo { Name : user . Anonymous , Groups : [] string { user . AllAuthenticated }}
82+ unauthenticated = & user. DefaultInfo { Name : user . Anonymous , Groups : [] string { user . AllUnauthenticated }}
6383)
6484
65- // withWarrants wraps the appliesToUser predicate to check for the base user and any warrants.
66- func withWarrants (appliesToUser appliesToUserFuncCtx ) appliesToUserFuncCtx {
67- var recursive appliesToUserFuncCtx
68- recursive = func (ctx context.Context , u user.Info , bindingSubject rbacv1.Subject , namespace string ) bool {
69- if appliesToUser (ctx , u , bindingSubject , namespace ) {
70- return true
85+ // EffectiveUsers flattens the warrants and scopes each user to the given cluster.
86+ func EffectiveUsers (clusterName logicalcluster.Name , u user.Info ) []user.Info {
87+ ret := make ([]user.Info , 0 , 2 )
88+
89+ var wantAuthenticated bool
90+ var wantUnauthenticated bool
91+
92+ var recursive func (u user.Info )
93+ recursive = func (u user.Info ) {
94+ if IsInScope (u , clusterName ) {
95+ ret = append (ret , u )
96+ } else {
97+ found := false
98+ for _ , g := range u .GetGroups () {
99+ if g == user .AllAuthenticated {
100+ found = true
101+ break
102+ }
103+ }
104+ wantAuthenticated = wantAuthenticated || found
105+ wantUnauthenticated = wantUnauthenticated || ! found
71106 }
72107
73108 if IsServiceAccount (u ) {
74109 if clusters := u .GetExtra ()[authserviceaccount .ClusterNameKey ]; len (clusters ) == 1 {
75110 nsNameSuffix := strings .TrimPrefix (u .GetName (), "system:serviceaccount:" )
76111 rewritten := & user.DefaultInfo {
77- Name : fmt .Sprintf ("system:kcp:serviceaccount:%s:%s" , clusters [0 ], nsNameSuffix ),
78- Groups : []string {user .AllAuthenticated },
79- Extra : u .GetExtra (),
112+ Name : fmt .Sprintf ("system:kcp:serviceaccount:%s:%s" , clusters [0 ], nsNameSuffix ),
113+ Extra : u .GetExtra (),
80114 }
81- if appliesToUser (ctx , rewritten , bindingSubject , namespace ) {
82- return true
115+ for _ , g := range u .GetGroups () {
116+ if g == user .AllAuthenticated {
117+ rewritten .Groups = []string {user .AllAuthenticated }
118+ break
119+ }
83120 }
121+ ret = append (ret , rewritten )
84122 }
85123 }
86124
@@ -100,47 +138,19 @@ func withWarrants(appliesToUser appliesToUserFuncCtx) appliesToUserFuncCtx {
100138 // warrants must be scoped to a cluster
101139 continue
102140 }
103- if recursive (ctx , wu , bindingSubject , namespace ) {
104- return true
105- }
141+ recursive (wu )
106142 }
107-
108- return false
109143 }
110- return recursive
111- }
112-
113- // withScopes wraps the appliesToUser predicate to check the scopes.
114- func withScopes (appliesToUser appliesToUserFunc ) appliesToUserFuncCtx {
115- return func (ctx context.Context , u user.Info , bindingSubject rbacv1.Subject , namespace string ) bool {
116- var clusterName logicalcluster.Name
117- if cluster := genericapirequest .ClusterFrom (ctx ); cluster != nil {
118- clusterName = cluster .Name
119- }
120- if IsInScope (u , clusterName ) && appliesToUser (u , bindingSubject , namespace ) {
121- return true
122- }
123- if appliesToUser (scopeDown (u ), bindingSubject , namespace ) {
124- return true
125- }
144+ recursive (u )
126145
127- return false
146+ if wantAuthenticated {
147+ ret = append (ret , authenticated )
128148 }
129- }
130-
131- var (
132- authenticated = & user.DefaultInfo {Name : user .Anonymous , Groups : []string {user .AllAuthenticated }}
133- unauthenticated = & user.DefaultInfo {Name : user .Anonymous , Groups : []string {user .AllUnauthenticated }}
134- )
135-
136- func scopeDown (u user.Info ) user.Info {
137- for _ , g := range u .GetGroups () {
138- if g == user .AllAuthenticated {
139- return authenticated
140- }
149+ if wantUnauthenticated {
150+ ret = append (ret , unauthenticated )
141151 }
142152
143- return unauthenticated
153+ return ret
144154}
145155
146156// IsServiceAccount returns true if the user is a service account.
@@ -195,28 +205,11 @@ func EffectiveGroups(ctx context.Context, u user.Info) sets.Set[string] {
195205 clusterName = cluster .Name
196206 }
197207
208+ eus := EffectiveUsers (clusterName , u )
198209 groups := sets .New [string ]()
199- var recursive func (u user.Info )
200- recursive = func (u user.Info ) {
201- if IsInScope (u , clusterName ) {
202- groups .Insert (u .GetGroups ()... )
203- } else {
204- for _ , g := range u .GetGroups () {
205- if g == user .AllAuthenticated {
206- groups .Insert (g )
207- }
208- }
209- }
210-
211- for _ , v := range u .GetExtra ()[WarrantExtraKey ] {
212- var w Warrant
213- if err := json .Unmarshal ([]byte (v ), & w ); err != nil {
214- continue
215- }
216- recursive (& user.DefaultInfo {Name : w .User , UID : w .UID , Groups : w .Groups , Extra : w .Extra })
217- }
210+ for _ , eu := range eus {
211+ groups .Insert (eu .GetGroups ()... )
218212 }
219- recursive (u )
220213
221214 return groups
222215}
0 commit comments