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

Attempting to delete an in-use group fails and leaves group in inconsistent state #398

Open
mbookman opened this issue Dec 18, 2019 · 0 comments

Comments

@mbookman
Copy link

Reproducible test case:

In Terra:

  1. Create a group: deleteable-test-group
  2. Create a workspace: deleteable-workspace
  3. Share deleteable-workspace with deleteable-test-group as Readers
  4. Try to delete the group deleteable-test-group

You will get an error message here:

Error deleting group
Error 409: group deleteable-test-group cannot be deleted because it is a member of
at least 1 other group
Source: sam

and in Terra, it appears that the group has not been deleted.

In the Google Cloud Console:

  1. Create a Cloud Storage bucket deleteable-bucket in a Cloud project you own
  2. In the Permissions tab for the bucket, try to Add Member [email protected]

You will get an error message:

Email addresses and domains must be associated with an active Google Account
or Google Apps account.

The underlying meaning of this message is that [email protected] does not exist.

Looking into the SAM code, this appears to be implemented here:

  def deleteManagedGroup(groupId: ResourceId): Future[Unit] =
    for {
      // order is important here, we want to make sure we do all the cloudExtensions calls before we touch ldap
      // so failures there do not leave ldap in a bad state
      // resourceService.deleteResource also does cloudExtensions.onGroupDelete first thing
      _ <- cloudExtensions.onGroupDelete(WorkbenchEmail(constructEmail(groupId.value)))
      managedGroupResourceId = FullyQualifiedResourceId(managedGroupType.name, groupId)
      _ <- resourceService.cloudDeletePolicies(managedGroupResourceId)
      _ <- directoryDAO.deleteGroup(WorkbenchGroupName(groupId.value)).unsafeToFuture()
      _ <- resourceService.deleteResource(managedGroupResourceId)
    } yield ()

Looking elsewhere I see in src/main/scala/org/broadinstitute/dsde/workbench/sam/directory/LdapDirectoryDAO.scala:

  override def deleteGroup(groupName: WorkbenchGroupName): IO[Unit] =
    for {
      ancestors <- listAncestorGroups(groupName)
      res <- if (ancestors.nonEmpty) {
        IO.raiseError(
          new WorkbenchExceptionWithErrorReport(
            ErrorReport(StatusCodes.Conflict, s"group ${groupName.value} cannot be deleted because it is a member of at least 1 other group")))
      } else {
        executeLdap(IO(ldapConnectionPool.delete(groupDn(groupName))).void)
      }
    } yield res```

So it looks to me like these steps complete successfully:

      _ <- cloudExtensions.onGroupDelete(WorkbenchEmail(constructEmail(groupId.value)))
      managedGroupResourceId = FullyQualifiedResourceId(managedGroupType.name, groupId)
      _ <- resourceService.cloudDeletePolicies(managedGroupResourceId)

and this fails:

      _ <- directoryDAO.deleteGroup(WorkbenchGroupName(groupId.value)).unsafeToFuture()

Leaving the group in an inconsistent state. Not sure the right solution here, since this is attempting to execute something atomic across multiple systems. A change that would help here would be to check:

      ancestors <- listAncestorGroups(groupName)
      res <- if (ancestors.nonEmpty) {

before attempting the deletion.

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

No branches or pull requests

1 participant