Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show actionable errors for collaborative deployment scenarios #1386

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

lennartkats-db
Copy link
Contributor

Changes

This adds diagnostics for collaborative (production) deployment scenarios, including:

  • Bob deploys a bundle that is normally deployed by Alice, but this fails because Bob can't write to /Users/Alice/.bundle.
  • Charlie deploys a bundle that is normally deployed by Alice, but this fails because he can't create a new pipeline where Alice would be the owner.
  • Alice deploys a bundle where she didn't list herself as one of the CAN_MANAGE users in permissions. That can work, but is probably a mistake.

Tests

Unit tests, manual testing.

@codecov-commenter
Copy link

codecov-commenter commented Jun 2, 2024

Codecov Report

Attention: Patch coverage is 75.56818% with 43 lines in your changes are missing coverage. Please review.

Project coverage is 53.75%. Comparing base (e22dd8a) to head (0b9feab).
Report is 125 commits behind head on main.

Files Patch % Lines
bundle/permissions/permission_diagnostics.go 87.60% 11 Missing and 4 partials ⚠️
libs/filer/workspace_files_client.go 0.00% 14 Missing ⚠️
bundle/config/mutator/run_as.go 81.81% 6 Missing ⚠️
bundle/deploy/terraform/apply.go 0.00% 4 Missing ⚠️
libs/filer/filer.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1386      +/-   ##
==========================================
+ Coverage   52.25%   53.75%   +1.50%     
==========================================
  Files         317      352      +35     
  Lines       18004    20410    +2406     
==========================================
+ Hits         9408    10972    +1564     
- Misses       7903     8636     +733     
- Partials      693      802     +109     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@lennartkats-db lennartkats-db changed the title [WIP] Show better errors for collaborative deployment scenarios Show better errors for collaborative deployment scenarios Jun 3, 2024
@lennartkats-db lennartkats-db changed the title Show better errors for collaborative deployment scenarios Show actionable errors for collaborative deployment scenarios Jun 3, 2024
bundle/config/mutator/run_as.go Show resolved Hide resolved
bundle/config/mutator/run_as.go Outdated Show resolved Hide resolved
bundle/config/mutator/run_as.go Show resolved Hide resolved
bundle/config/resources.go Outdated Show resolved Hide resolved
bundle/deploy/files/upload.go Show resolved Hide resolved
libs/diag/diagnostic.go Outdated Show resolved Hide resolved
libs/diag/diagnostic.go Show resolved Hide resolved
libs/diag/id.go Show resolved Hide resolved
libs/filer/filer.go Show resolved Hide resolved
libs/filer/workspace_files_client.go Outdated Show resolved Hide resolved
@lennartkats-db lennartkats-db force-pushed the cp-better-errors branch 2 times, most recently from 8d26485 to 16b80ea Compare July 6, 2024 19:37
@lennartkats-db
Copy link
Contributor Author

@pietern could you take another look?

bundle/config/resources.go Outdated Show resolved Hide resolved
bundle/permissions/permission_diagnostics.go Show resolved Hide resolved
bundle/permissions/permission_diagnostics.go Outdated Show resolved Hide resolved
bundle/permissions/permission_diagnostics.go Show resolved Hide resolved

assistance := "For assistance, contact the owners of this project."
if len(managersSlice) > 0 {
assistance = fmt.Sprintf("For assistance, users or groups with appropriate permissions may include: %s.", strings.Join(managersSlice, ", "))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping.

}

func ReportPermissionDenied(ctx context.Context, b *bundle.Bundle, path string) diag.Diagnostics {
log.Errorf(ctx, "Failed to update %v", path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping. If this is not the case, please include a comment stating why this log statement shouldn't be removed.

bundle/tests/run_as_test.go Outdated Show resolved Hide resolved
libs/filer/workspace_files_client.go Outdated Show resolved Hide resolved
@pietern
Copy link
Contributor

pietern commented Jul 15, 2024

@shreyas-goenka Can you take a pass as this as well?

@shreyas-goenka
Copy link
Contributor

Missed the ping, taking a look.

Copy link
Contributor

@shreyas-goenka shreyas-goenka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work end to end? Can Bob collaborate on a DAB deployed by Alice if he has CAN_MANAGE?

I recall there being some validation on the Terraform provider side that would fail even if Bob has CAN_MANAGE permissions set.

@@ -166,11 +166,21 @@ func (w *WorkspaceFilesClient) Write(ctx context.Context, name string, reader io
// Create parent directory.
err = w.workspaceClient.Workspace.MkdirsByPath(ctx, path.Dir(absPath))
if err != nil {
if errors.As(err, &aerr) && aerr.StatusCode == http.StatusForbidden {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move it out of the err != nil closure. errors.As automatically asserts that error is not nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pleas note the errors.As() is a special case: the larger if err != nil also reports an error for non-Forbidden errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant we could reduce a level of indentation, like:

if errors.As(err, &aerr) && aerr.StatusCode == http.StatusForbidden {
  return PermissionError{absPath}
}
if err != nil {
  return fmt.Errorf("unable to mkdir to write file %s: %w", absPath, err)
}

libs/filer/workspace_files_client.go Show resolved Hide resolved
bundle/permissions/terraform_errors.go Outdated Show resolved Hide resolved
bundle/permissions/permission_diagnostics.go Outdated Show resolved Hide resolved
bundle/permissions/terraform_errors.go Show resolved Hide resolved
bundle/permissions/mutator.go Show resolved Hide resolved
@lennartkats-db
Copy link
Contributor Author

@shreyas-goenka

Does this work end to end? Can Bob collaborate on a DAB deployed by Alice if he has CAN_MANAGE?

I recall there being some validation on the Terraform provider side that would fail even if Bob has CAN_MANAGE permissions set.

Yes, though that scenario requires the use of an explicit "OWNER: Alice" permission. Which is supported via #1387.

github-merge-queue bot pushed a commit that referenced this pull request Sep 3, 2024
## Changes

This updates the templates to include a `permissions` section. Having a
permissions section is a best practice, is helpful to understand the
notion of permissions, and helps diagnose permission errors
(#1386).

This is a cherry-pick from #1387.

This change was verified to work both in dev and prod. Existing unit
tests validate the validity of the templates in these modes.
Copy link
Contributor

@pietern pietern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan for the diagnostic IDs after this PR?

Right now they're included in the error string but not in the rendered list of diags.

libs/filer/workspace_files_client.go Outdated Show resolved Hide resolved
bundle/deploy/files/upload.go Outdated Show resolved Hide resolved
bundle/deploy/lock/acquire.go Show resolved Hide resolved
bundle/permissions/permission_diagnostics.go Outdated Show resolved Hide resolved
//
// Note that since the workspace API doesn't always distinguish between permission denied and path errors,
// we must treat this as a "possible permission error". See acquire.go for more about this.
func ReportPossiblePermissionDenied(ctx context.Context, b *bundle.Bundle, path string) diag.Diagnostics {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a helper unrelated to the mutator. Please move it to a dedicated file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

// Note that since the workspace API doesn't always distinguish between permission denied and path errors,
// we must treat this as a "possible permission error". See acquire.go for more about this.
func ReportPossiblePermissionDenied(ctx context.Context, b *bundle.Bundle, path string) diag.Diagnostics {
log.Errorf(ctx, "Failed to update, encountered possible permission error: %v", path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear if there was an update; we don't have access to the error or the intent here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't "possible permission" error cover what we know? The intent is just logging so maintainers can determine what's going on.

// But we're still seeing permission errors. So someone else will need
// to redeploy the bundle with the right set of permissions.
return diag.Diagnostics{{
Summary: fmt.Sprintf("access denied while updating deployment permissions as %s.\n"+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error above is more apt here: unable to deploy to %s as %s..

We cannot assert if the intent is to update deployment permissions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

bundle/phases/initialize.go Show resolved Hide resolved
@pietern
Copy link
Contributor

pietern commented Sep 3, 2024

We discussed this a while back; I'd like to get integration test coverage for the permission errors on the filer. It's implemented only for the workspace files client now, not for the others (for ex the files API).

@lennartkats-db
Copy link
Contributor Author

@pietern

We discussed this a while back; I'd like to get integration test coverage for the permission errors on the filer. It's implemented only for the workspace files client now, not for the others (for ex the files API).

Didn't we conclude that we would just not change the logic of the filer? I reverted that change.

@lennartkats-db
Copy link
Contributor Author

@pietern Updated the PR, processing all the new comments. I'd really like to get this merged.

bundle/permissions/permission_diagnostics.go Outdated Show resolved Hide resolved
bundle/permissions/permission_diagnostics_test.go Outdated Show resolved Hide resolved
user := b.Config.Workspace.CurrentUser.DisplayName
if user == "" {
user = b.Config.Workspace.CurrentUser.UserName
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the other PR today, I now look at this and see it will show the display name for regular users.

It will affect the error message shown. I think for regular users we better show the email address.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to just show the email address in errors.

if otherManagers.Size() > 0 {
assistance = fmt.Sprintf(
"For assistance, users or groups with appropriate permissions may include: %s.",
strings.Join(otherManagers.Values(), ", "),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not sorted and is the cause of the test assertion failure in the latest test run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants