authorizeRequest returns true if the request is authorized. The returned []string are warnings that aid in debugging. These messages do not prevent authorization, but may indicate that the request is not configured correctly. If an error is returned, the request should be aborted with a 500 error.
(ctx context.Context, roles *rbac.Subject, dbReq *databaseRequest)
| 266 | // but may indicate that the request is not configured correctly. |
| 267 | // If an error is returned, the request should be aborted with a 500 error. |
| 268 | func (p *DBTokenProvider) authorizeRequest(ctx context.Context, roles *rbac.Subject, dbReq *databaseRequest) (bool, []string, error) { |
| 269 | var warnings []string |
| 270 | accessMethod := dbReq.AccessMethod |
| 271 | if accessMethod == "" { |
| 272 | accessMethod = AccessMethodPath |
| 273 | } |
| 274 | isPathApp := accessMethod == AccessMethodPath |
| 275 | |
| 276 | // If path-based app sharing is disabled (which is the default), we can |
| 277 | // force the sharing level to be "owner" so that the user can only access |
| 278 | // their own apps. |
| 279 | // |
| 280 | // Site owners are blocked from accessing path-based apps unless the |
| 281 | // Dangerous.AllowPathAppSiteOwnerAccess flag is enabled in the check below. |
| 282 | sharingLevel := dbReq.AppSharingLevel |
| 283 | if isPathApp && !p.DeploymentValues.Dangerous.AllowPathAppSharing.Value() { |
| 284 | if dbReq.AppSharingLevel != database.AppSharingLevelOwner { |
| 285 | // This is helpful for debugging, and ok to leak to the user. |
| 286 | // This is because the app has the sharing level set to something that |
| 287 | // should be shared, but we are disabling it from a deployment wide |
| 288 | // flag. So the template should be fixed to set the sharing level to |
| 289 | // "owner" instead and this will not appear. |
| 290 | warnings = append(warnings, fmt.Sprintf("unable to use configured sharing level %q because path-based app sharing is disabled (see --dangerous-allow-path-app-sharing), using sharing level \"owner\" instead", sharingLevel)) |
| 291 | } |
| 292 | sharingLevel = database.AppSharingLevelOwner |
| 293 | } |
| 294 | |
| 295 | // Short circuit if not authenticated. |
| 296 | if roles == nil { |
| 297 | // The user is not authenticated, so they can only access the app if it |
| 298 | // is public. |
| 299 | return sharingLevel == database.AppSharingLevelPublic, warnings, nil |
| 300 | } |
| 301 | |
| 302 | // Block anyone from accessing workspaces they don't own in path-based apps |
| 303 | // unless the admin disables this security feature. This blocks site-owners |
| 304 | // from accessing any apps from any user's workspaces. |
| 305 | // |
| 306 | // When the Dangerous.AllowPathAppSharing flag is not enabled, the sharing |
| 307 | // level will be forced to "owner", so this check will always be true for |
| 308 | // workspaces owned by different users. |
| 309 | if isPathApp && |
| 310 | sharingLevel == database.AppSharingLevelOwner && |
| 311 | dbReq.Workspace.OwnerID.String() != roles.ID && |
| 312 | !p.DeploymentValues.Dangerous.AllowPathAppSiteOwnerAccess.Value() { |
| 313 | // This is not ideal to check for the 'owner' role, but we are only checking |
| 314 | // to determine whether to show a warning for debugging reasons. This does |
| 315 | // not do any authz checks, so it is ok. |
| 316 | if slices.Contains(roles.Roles.Names(), rbac.RoleOwner()) { |
| 317 | warnings = append(warnings, "path-based apps with \"owner\" share level are only accessible by the workspace owner (see --dangerous-allow-path-app-site-owner-access)") |
| 318 | } |
| 319 | return false, warnings, nil |
| 320 | } |
| 321 | |
| 322 | // Figure out which RBAC resource to check. For terminals we use execution |
| 323 | // instead of application connect. |
| 324 | var ( |
| 325 | rbacAction policy.Action = policy.ActionApplicationConnect |
no test coverage detected