Skip to content

Commit 242e852

Browse files
committed
scope authn infos to the given logicalcluster, add test to ensure it works
On-behalf-of: @SAP [email protected]
1 parent 39d6d4e commit 242e852

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed

pkg/authentication/workspace.go renamed to pkg/authentication/authenticators.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ limitations under the License.
1717
package authentication
1818

1919
import (
20+
"fmt"
2021
"net/http"
2122

2223
"k8s.io/apiserver/pkg/authentication/authenticator"
24+
"k8s.io/apiserver/pkg/authentication/user"
25+
26+
"github.com/kcp-dev/kcp/pkg/proxy/lookup"
2327
)
2428

2529
type workspaceAuthenticator struct{}
@@ -36,3 +40,37 @@ func (a *workspaceAuthenticator) AuthenticateRequest(req *http.Request) (*authen
3640

3741
return reqAuthenticator.AuthenticateRequest(req)
3842
}
43+
44+
type clusterScoper struct {
45+
delegate authenticator.Request
46+
}
47+
48+
func withClusterScope(delegate authenticator.Request) authenticator.Request {
49+
return &clusterScoper{
50+
delegate: delegate,
51+
}
52+
}
53+
54+
func (a *clusterScoper) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
55+
response, authenticated, ok := a.delegate.AuthenticateRequest(req)
56+
if authenticated {
57+
cluster := lookup.ClusterNameFrom(req.Context())
58+
59+
extra := response.User.GetExtra()
60+
if extra == nil {
61+
extra = map[string][]string{}
62+
}
63+
if true {
64+
extra["authentication.kcp.io/scopes"] = append(extra["authentication.kcp.io/scopes"], fmt.Sprintf("cluster:%s", cluster))
65+
}
66+
67+
response.User = &user.DefaultInfo{
68+
Name: response.User.GetName(),
69+
UID: response.User.GetUID(),
70+
Groups: response.User.GetGroups(),
71+
Extra: extra,
72+
}
73+
}
74+
75+
return response, authenticated, ok
76+
}

pkg/authentication/filters.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ func WithWorkspaceAuthResolver(handler http.Handler, authIndex AuthenticatorInde
4343
return
4444
}
4545

46+
// make the authenticator always add the target cluster to the user scopes
47+
authn = withClusterScope(authn)
48+
4649
req = req.WithContext(WithWorkspaceAuthenticator(req.Context(), authn))
4750
handler.ServeHTTP(w, req)
4851
})

pkg/server/localproxy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ func WithLocalProxy(
199199
cluster.Name = clusterName
200200
}
201201
ctx = request.WithCluster(ctx, cluster)
202+
ctx = lookup.WithClusterName(ctx, cluster.Name)
202203
ctx = lookup.WithWorkspaceType(ctx, r.Type)
203204

204205
handler.ServeHTTP(w, req.WithContext(ctx))

test/e2e/authentication/workspace_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/stretchr/testify/require"
2727
"github.com/xrstf/mockoidc"
2828

29+
authenticationv1 "k8s.io/api/authentication/v1"
2930
rbacv1 "k8s.io/api/rbac/v1"
3031
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3132
"k8s.io/apimachinery/pkg/util/wait"
@@ -239,6 +240,72 @@ func TestWorkspaceOIDC(t *testing.T) {
239240
}
240241
}
241242

243+
func TestUserScope(t *testing.T) {
244+
framework.Suite(t, "control-plane")
245+
246+
ctx := context.Background()
247+
248+
// start kcp and setup clients
249+
server := kcptesting.SharedKcpServer(t)
250+
251+
baseWsPath, _ := kcptesting.NewWorkspaceFixture(t, server, logicalcluster.NewPath("root"), kcptesting.WithNamePrefix("oidc-scope"))
252+
253+
kcpConfig := server.BaseConfig(t)
254+
kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(kcpConfig)
255+
require.NoError(t, err)
256+
kcpClusterClient, err := kcpclientset.NewForConfig(kcpConfig)
257+
require.NoError(t, err)
258+
259+
mock, ca := startMockOIDC(t, server)
260+
authConfig := createWorkspaceAuthentication(t, ctx, kcpClusterClient, baseWsPath, mock, ca)
261+
wsType := createWorkspaceType(t, ctx, kcpClusterClient, baseWsPath, authConfig)
262+
263+
// create a new workspace with our new type
264+
t.Log("Creating Workspaces...")
265+
teamPath, teamWs := kcptesting.NewWorkspaceFixture(t, server, baseWsPath, kcptesting.WithName("team-a"), kcptesting.WithType(baseWsPath, tenancyv1alpha1.WorkspaceTypeName(wsType)))
266+
267+
var (
268+
userName = "peter"
269+
userEmail = "[email protected]"
270+
userGroups = []string{"developers", "admins"}
271+
expectedGroups = []string{}
272+
)
273+
274+
for _, group := range userGroups {
275+
expectedGroups = append(expectedGroups, "oidc:"+group)
276+
}
277+
278+
grantWorkspaceAccess(t, ctx, kubeClusterClient, teamPath, []rbacv1.Subject{{
279+
Kind: "User",
280+
Name: "oidc:" + userEmail,
281+
}})
282+
283+
token := createOIDCToken(t, mock, userName, userEmail, userGroups)
284+
285+
peterClient, err := kcpkubernetesclientset.NewForConfig(framework.ConfigWithToken(token, kcpConfig))
286+
require.NoError(t, err)
287+
288+
t.Logf("Creating SelfSubjectAccessReview in %s", teamPath)
289+
290+
var review *authenticationv1.SelfSubjectReview
291+
require.Eventually(t, func() bool {
292+
request := &authenticationv1.SelfSubjectReview{}
293+
294+
var err error
295+
review, err = peterClient.Cluster(teamPath).AuthenticationV1().SelfSubjectReviews().Create(ctx, request, metav1.CreateOptions{})
296+
if err != nil {
297+
t.Log(err)
298+
}
299+
300+
return err == nil
301+
}, wait.ForeverTestTimeout, 500*time.Millisecond)
302+
303+
user := review.Status.UserInfo
304+
require.Equal(t, "oidc:"+userEmail, user.Username)
305+
require.Subset(t, user.Groups, expectedGroups)
306+
require.Equal(t, user.Extra["authentication.kcp.io/scopes"], authenticationv1.ExtraValue{"cluster:" + teamWs.Spec.Cluster})
307+
}
308+
242309
func createWorkspaceAuthentication(t *testing.T, ctx context.Context, client kcpclientset.ClusterInterface, workspace logicalcluster.Path, mock *mockoidc.MockOIDC, ca *crypto.CA) string {
243310
name := fmt.Sprintf("mockoidc-%d", rand.Int())
244311

0 commit comments

Comments
 (0)