Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions pkg/authorization/authorizer/scope/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,12 @@ const (
UserInfo = UserIndicator + "info"
UserAccessCheck = UserIndicator + "check-access"

// UserListProject gives explicit permission to see the projects a user can see. This is often used to prime secondary ACL systems
// UserListScopedProjects gives explicit permission to see the projects that this token can see.
UserListScopedProjects = UserIndicator + "list-scoped-projects"

// UserListAllProjects gives explicit permission to see the projects a user can see. This is often used to prime secondary ACL systems
// unrelated to openshift and to display projects for selection in a secondary UI.
UserListProject = UserIndicator + "list-projects"
UserListAllProjects = UserIndicator + "list-projects"

// UserFull includes all permissions of the user
UserFull = UserIndicator + "full"
Expand All @@ -138,7 +141,7 @@ func (userEvaluator) Handles(scope string) bool {

func (userEvaluator) Validate(scope string) error {
switch scope {
case UserFull, UserInfo, UserAccessCheck, UserListProject:
case UserFull, UserInfo, UserAccessCheck, UserListScopedProjects, UserListAllProjects:
return nil
}

Expand All @@ -151,7 +154,9 @@ func (userEvaluator) Describe(scope string) (string, string, error) {
return "Read-only access to your user information (including username, identities, and group membership)", "", nil
case UserAccessCheck:
return `Read-only access to view your privileges (for example, "can I create builds?")`, "", nil
case UserListProject:
case UserListScopedProjects:
return `Read-only access to list your projects viewable with this token and view their metadata (display name, description, etc.)`, "", nil
case UserListAllProjects:
return `Read-only access to list your projects and view their metadata (display name, description, etc.)`, "", nil
case UserFull:
return `Full read/write access with all of your permissions`, `Includes any access you have to escalating resources like secrets`, nil
Expand All @@ -171,10 +176,15 @@ func (userEvaluator) ResolveRules(scope, namespace string, clusterPolicyGetter c
{Verbs: sets.NewString("create"), APIGroups: []string{authorizationapi.GroupName}, Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), AttributeRestrictions: &authorizationapi.IsPersonalSubjectAccessReview{}},
authorizationapi.NewRule("create").Groups(authorizationapi.GroupName).Resources("selfsubjectrulesreviews").RuleOrDie(),
}, nil
case UserListProject:
case UserListScopedProjects:
return []authorizationapi.PolicyRule{
{Verbs: sets.NewString("list", "watch"), APIGroups: []string{projectapi.GroupName}, Resources: sets.NewString("projects")},
}, nil
case UserListAllProjects:
return []authorizationapi.PolicyRule{
{Verbs: sets.NewString("list", "watch"), APIGroups: []string{projectapi.GroupName}, Resources: sets.NewString("projects")},
{Verbs: sets.NewString("get"), APIGroups: []string{kapi.GroupName}, Resources: sets.NewString("namespaces")},
}, nil
case UserFull:
return []authorizationapi.PolicyRule{
{Verbs: sets.NewString("*"), APIGroups: []string{"*"}, Resources: sets.NewString("*")},
Expand All @@ -187,7 +197,7 @@ func (userEvaluator) ResolveRules(scope, namespace string, clusterPolicyGetter c

func (userEvaluator) ResolveGettableNamespaces(scope string, clusterPolicyGetter client.ClusterPolicyLister) ([]string, error) {
switch scope {
case UserFull:
case UserFull, UserListAllProjects:
return []string{"*"}, nil
default:
return []string{}, nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/authorization/authorizer/scope/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func TestUserEvaluator(t *testing.T) {
numRules: 4,
},
{
name: "list-projects",
scopes: []string{UserListProject},
name: "list--scoped-projects",
scopes: []string{UserListScopedProjects},
numRules: 2,
},
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/serviceaccounts/oauthclient/oauthclientregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ func (a *saOAuthClientAdapter) GetClient(ctx kapi.Context, name string) (*oautha

func getScopeRestrictionsFor(namespace, name string) []oauthapi.ScopeRestriction {
return []oauthapi.ScopeRestriction{
{ExactValues: []string{scopeauthorizer.UserInfo, scopeauthorizer.UserAccessCheck}},
{ExactValues: []string{
scopeauthorizer.UserInfo,
scopeauthorizer.UserAccessCheck,
scopeauthorizer.UserListScopedProjects,
scopeauthorizer.UserListAllProjects,
}},
{ClusterRole: &oauthapi.ClusterRoleScopeRestriction{RoleNames: []string{"*"}, Namespaces: []string{namespace}, AllowEscalation: true}},
}
}
Expand Down
5 changes: 4 additions & 1 deletion test/cmd/authentication.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ whoamitoken="$(oc process -f "${OS_ROOT}/test/testdata/authentication/scoped-tok
os::cmd::expect_success_and_text "oc get user/~ --token='${whoamitoken}'" "${username}"
os::cmd::expect_failure_and_text "oc get pods --token='${whoamitoken}' -n '${project}'" "prevent this action; User \"scoped-user\" cannot list pods in project \"${project}\""

listprojecttoken="$(oc process -f "${OS_ROOT}/test/testdata/authentication/scoped-token-template.yaml" TOKEN_PREFIX=listproject SCOPE=user:list-projects USER_NAME="${username}" USER_UID="${useruid}" | oc create -f - -o name | awk -F/ '{print $2}')"
listprojecttoken="$(oc process -f "${OS_ROOT}/test/testdata/authentication/scoped-token-template.yaml" TOKEN_PREFIX=listproject SCOPE=user:list-scoped-projects USER_NAME="${username}" USER_UID="${useruid}" | oc create -f - -o name | awk -F/ '{print $2}')"
# this token doesn't have rights to see any projects even though it can hit the list endpoint, so an empty list is correct
# we'll add another scope that allows listing all known projects even if this token has no other powers in them.
os::cmd::expect_success_and_not_text "oc get projects --token='${listprojecttoken}'" "${project}"
os::cmd::expect_failure_and_text "oc get user/~ --token='${listprojecttoken}'" 'prevent this action; User "scoped-user" cannot get users at the cluster scope'
os::cmd::expect_failure_and_text "oc get pods --token='${listprojecttoken}' -n '${project}'" "prevent this action; User \"scoped-user\" cannot list pods in project \"${project}\""

listprojecttoken="$(oc process -f "${OS_ROOT}/test/testdata/authentication/scoped-token-template.yaml" TOKEN_PREFIX=listallprojects SCOPE=user:list-projects USER_NAME="${username}" USER_UID="${useruid}" | oc create -f - -o name | awk -F/ '{print $2}')"
os::cmd::expect_success_and_text "oc get projects --token='${listprojecttoken}'" "${project}"

adminnonescalatingpowerstoken="$(oc process -f "${OS_ROOT}/test/testdata/authentication/scoped-token-template.yaml" TOKEN_PREFIX=admin SCOPE=role:admin:* USER_NAME="${username}" USER_UID="${useruid}" | oc create -f - -o name | awk -F/ '{print $2}')"
os::cmd::expect_failure_and_text "oc get user/~ --token='${adminnonescalatingpowerstoken}'" 'prevent this action; User "scoped-user" cannot get users at the cluster scope'
os::cmd::expect_failure_and_text "oc get secrets --token='${adminnonescalatingpowerstoken}' -n '${project}'" "prevent this action; User \"scoped-user\" cannot list secrets in project \"${project}\""
Expand Down
6 changes: 3 additions & 3 deletions test/integration/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ func TestScopedProjectAccess(t *testing.T) {
}

oneTwoBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{
scope.UserListProject,
scope.UserListScopedProjects,
scope.ClusterRoleIndicator + "view:one",
scope.ClusterRoleIndicator + "view:two",
})
Expand All @@ -330,13 +330,13 @@ func TestScopedProjectAccess(t *testing.T) {
}

twoThreeBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{
scope.UserListProject,
scope.UserListScopedProjects,
scope.ClusterRoleIndicator + "view:two",
scope.ClusterRoleIndicator + "view:three",
})

allBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{
scope.UserListProject,
scope.UserListScopedProjects,
scope.ClusterRoleIndicator + "view:*",
})
if err != nil {
Expand Down