1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

[SM-755] Add EF Secrets Manager cleanup on deletes (#3228)

* Add Delete Cascade for EF AccessPolicy table

* Add AP removal on EF user deletion

* Remove SM entities on EF org delete
This commit is contained in:
Thomas Avery
2023-09-21 17:22:08 -05:00
committed by GitHub
parent 90d600db9d
commit 46faecaade
13 changed files with 7008 additions and 33 deletions

View File

@ -144,27 +144,42 @@ public class OrganizationRepository : Repository<Core.Entities.Organization, Org
var dbContext = GetDatabaseContext(scope);
await dbContext.UserBumpAccountRevisionDateByOrganizationIdAsync(organization.Id);
var deleteCiphersTransaction = await dbContext.Database.BeginTransactionAsync();
dbContext.Ciphers.RemoveRange(
dbContext.Ciphers.Where(c => c.UserId == null && c.OrganizationId == organization.Id));
await dbContext.Ciphers.Where(c => c.UserId == null && c.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await deleteCiphersTransaction.CommitAsync();
var organizationDeleteTransaction = await dbContext.Database.BeginTransactionAsync();
dbContext.SsoUsers.RemoveRange(dbContext.SsoUsers.Where(su => su.OrganizationId == organization.Id));
dbContext.SsoConfigs.RemoveRange(dbContext.SsoConfigs.Where(sc => sc.OrganizationId == organization.Id));
var collectionUsers = from cu in dbContext.CollectionUsers
join ou in dbContext.OrganizationUsers on cu.OrganizationUserId equals ou.Id
where ou.OrganizationId == organization.Id
select cu;
dbContext.CollectionUsers.RemoveRange(collectionUsers);
dbContext.OrganizationUsers.RemoveRange(
dbContext.OrganizationUsers.Where(ou => ou.OrganizationId == organization.Id));
dbContext.ProviderOrganizations.RemoveRange(
dbContext.ProviderOrganizations.Where(po => po.OrganizationId == organization.Id));
await dbContext.SsoUsers.Where(su => su.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.SsoConfigs.Where(sc => sc.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.CollectionUsers.Where(cu => cu.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUser.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.OrganizationUsers.Where(ou => ou.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ProviderOrganizations.Where(po => po.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.GroupServiceAccountAccessPolicy.Where(ap => ap.GrantedServiceAccount.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.Project.Where(p => p.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.Secret.Where(s => s.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ApiKeys.Where(ak => ak.ServiceAccount.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.ServiceAccount.Where(sa => sa.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
// The below section are 3 SPROCS in SQL Server but are only called by here
dbContext.OrganizationApiKeys.RemoveRange(
dbContext.OrganizationApiKeys.Where(oa => oa.OrganizationId == organization.Id));
dbContext.OrganizationConnections.RemoveRange(
dbContext.OrganizationConnections.Where(oc => oc.OrganizationId == organization.Id));
await dbContext.OrganizationApiKeys.Where(oa => oa.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
await dbContext.OrganizationConnections.Where(oc => oc.OrganizationId == organization.Id)
.ExecuteDeleteAsync();
var sponsoringOrgs = await dbContext.OrganizationSponsorships
.Where(os => os.SponsoringOrganizationId == organization.Id)
.ToListAsync();

View File

@ -93,6 +93,11 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
.Where(gu => gu.OrganizationUserId == organizationUserId);
dbContext.GroupUsers.RemoveRange(groupUsers);
dbContext.UserProjectAccessPolicy.RemoveRange(
dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUserId == organizationUserId));
dbContext.UserServiceAccountAccessPolicy.RemoveRange(
dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUserId == organizationUserId));
var orgSponsorships = await dbContext.OrganizationSponsorships
.Where(os => os.SponsoringOrganizationUserId == organizationUserId)
.ToListAsync();
@ -325,7 +330,7 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
var userIds = users.Select(u => u.Id);
var userIdEntities = dbContext.OrganizationUsers.Where(x => userIds.Contains(x.Id));
// Query groups/collections separately to avoid cartesian explosion
// Query groups/collections separately to avoid cartesian explosion
if (includeGroups)
{
groups = (await (from gu in dbContext.GroupUsers

View File

@ -167,6 +167,10 @@ public class UserRepository : Repository<Core.Entities.User, User, Guid>, IUserR
where ou.UserId == user.Id
select gu;
dbContext.GroupUsers.RemoveRange(groupUsers);
dbContext.UserProjectAccessPolicy.RemoveRange(
dbContext.UserProjectAccessPolicy.Where(ap => ap.OrganizationUser.UserId == user.Id));
dbContext.UserServiceAccountAccessPolicy.RemoveRange(
dbContext.UserServiceAccountAccessPolicy.Where(ap => ap.OrganizationUser.UserId == user.Id));
dbContext.OrganizationUsers.RemoveRange(dbContext.OrganizationUsers.Where(ou => ou.UserId == user.Id));
dbContext.ProviderUsers.RemoveRange(dbContext.ProviderUsers.Where(pu => pu.UserId == user.Id));
dbContext.SsoUsers.RemoveRange(dbContext.SsoUsers.Where(su => su.UserId == user.Id));

View File

@ -39,6 +39,12 @@ public class UserProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfigu
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(UserProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.UserAccessPolicies)
.HasForeignKey(nameof(UserProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@ -67,6 +73,18 @@ public class GroupProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfig
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(GroupProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.GroupAccessPolicies)
.HasForeignKey(nameof(GroupProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
builder
.HasOne(e => e.Group)
.WithMany()
.HasForeignKey(nameof(GroupProjectAccessPolicy.GroupId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@ -81,6 +99,12 @@ public class GroupServiceAccountAccessPolicyEntityTypeConfiguration : IEntityTyp
builder
.Property(e => e.GrantedServiceAccountId)
.HasColumnName(nameof(GroupServiceAccountAccessPolicy.GrantedServiceAccountId));
builder
.HasOne(e => e.Group)
.WithMany()
.HasForeignKey(nameof(GroupProjectAccessPolicy.GroupId))
.OnDelete(DeleteBehavior.Cascade);
}
}
@ -95,5 +119,11 @@ public class ServiceAccountProjectAccessPolicyEntityTypeConfiguration : IEntityT
builder
.Property(e => e.GrantedProjectId)
.HasColumnName(nameof(ServiceAccountProjectAccessPolicy.GrantedProjectId));
builder
.HasOne(e => e.GrantedProject)
.WithMany(e => e.ServiceAccountAccessPolicies)
.HasForeignKey(nameof(ServiceAccountProjectAccessPolicy.GrantedProjectId))
.OnDelete(DeleteBehavior.Cascade);
}
}