mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: show selected owner's external auth when creating a workspace (#26653)
This commit is contained in:
@@ -837,6 +837,28 @@ var (
|
||||
}),
|
||||
Scope: rbac.ScopeAll,
|
||||
}.WithCachedASTValue()
|
||||
|
||||
// subjectExternalAuthCoordinator is used to check whether a user has configured
|
||||
// external auth providers or not when an admin is creating a workspace for
|
||||
// another user.
|
||||
subjectExternalAuthCoordinator = rbac.Subject{
|
||||
Type: rbac.SubjectTypeExternalAuthCoordinator,
|
||||
FriendlyName: "External Auth Coordinator",
|
||||
ID: uuid.Nil.String(),
|
||||
Roles: rbac.Roles([]rbac.Role{
|
||||
{
|
||||
Identifier: rbac.RoleIdentifier{Name: "external-auth-coordinator"},
|
||||
DisplayName: "External Auth Coordinator",
|
||||
Site: rbac.Permissions(map[string][]policy.Action{
|
||||
// policy.ActionUpdatePersonal allows us to refresh tokens.
|
||||
rbac.ResourceUser.Type: {policy.ActionReadPersonal, policy.ActionUpdatePersonal},
|
||||
}),
|
||||
User: []rbac.Permission{},
|
||||
ByOrgID: map[string]rbac.OrgPermissions{},
|
||||
},
|
||||
}),
|
||||
Scope: rbac.ScopeAll,
|
||||
}.WithCachedASTValue()
|
||||
)
|
||||
|
||||
// AsProvisionerd returns a context with an actor that has permissions required
|
||||
@@ -985,6 +1007,12 @@ func AsSCIMProvisioner(ctx context.Context) context.Context {
|
||||
return As(ctx, subjectSCIM)
|
||||
}
|
||||
|
||||
// AsExternalAuthCoordinator returns a context with an actor that has permission to
|
||||
// read and refresh any user's external auth links.
|
||||
func AsExternalAuthCoordinator(ctx context.Context) context.Context {
|
||||
return As(ctx, subjectExternalAuthCoordinator)
|
||||
}
|
||||
|
||||
var AsRemoveActor = rbac.Subject{
|
||||
ID: "remove-actor",
|
||||
}
|
||||
|
||||
@@ -7633,3 +7633,48 @@ func TestAsChatd(t *testing.T) {
|
||||
require.Error(t, err, "provisioner daemon read should be denied")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAsExternalAuthChecker(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := dbauthz.AsExternalAuthCoordinator(context.Background())
|
||||
actor, ok := dbauthz.ActorFromContext(ctx)
|
||||
require.True(t, ok, "actor must be present")
|
||||
|
||||
auth := rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
|
||||
|
||||
t.Run("AllowedActions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Reading and refreshing a user's external auth link requires personal
|
||||
// read and update on the user resource.
|
||||
for _, action := range []policy.Action{
|
||||
policy.ActionReadPersonal, policy.ActionUpdatePersonal,
|
||||
} {
|
||||
err := auth.Authorize(ctx, actor, action, rbac.ResourceUser)
|
||||
require.NoError(t, err, "user %s should be allowed", action)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DeniedActions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// No general user read/write, only personal external auth access.
|
||||
for _, action := range []policy.Action{
|
||||
policy.ActionRead, policy.ActionCreate,
|
||||
policy.ActionUpdate, policy.ActionDelete,
|
||||
} {
|
||||
err := auth.Authorize(ctx, actor, action, rbac.ResourceUser)
|
||||
require.Error(t, err, "user %s should be denied", action)
|
||||
}
|
||||
|
||||
// Unlike AsSystemRestricted, this actor cannot read other resources.
|
||||
for _, res := range []rbac.Object{
|
||||
rbac.ResourceWorkspace, rbac.ResourceTemplate,
|
||||
rbac.ResourceApiKey, rbac.ResourceOrganization,
|
||||
} {
|
||||
err := auth.Authorize(ctx, actor, policy.ActionRead, res)
|
||||
require.Error(t, err, "%s read should be denied", res.Type)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user