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

[SM-1256] Add BulkSecretAuthorizationHandler (#4099)

* Add AccessToSecretsAsync to the repository

* Add BulkSecretAuthorizationHandler

* Update controller to use the new authz handler

* Add integration test coverage
This commit is contained in:
Thomas Avery
2024-07-09 10:06:33 -05:00
committed by GitHub
parent 313eef49f0
commit acc4808509
10 changed files with 484 additions and 72 deletions

View File

@ -260,25 +260,13 @@ public class SecretsController : Controller
throw new NotFoundException();
}
// Ensure all secrets belong to the same organization.
var organizationId = secrets.First().OrganizationId;
if (secrets.Any(secret => secret.OrganizationId != organizationId) ||
!_currentContext.AccessSecretsManager(organizationId))
var authorizationResult = await _authorizationService.AuthorizeAsync(User, secrets, BulkSecretOperations.ReadAll);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
foreach (var secret in secrets)
{
var authorizationResult = await _authorizationService.AuthorizeAsync(User, secret, SecretOperations.Read);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
}
await LogSecretsRetrievalAsync(organizationId, secrets);
await LogSecretsRetrievalAsync(secrets.First().OrganizationId, secrets);
var responses = secrets.Select(s => new BaseSecretResponseModel(s));
return new ListResponseModel<BaseSecretResponseModel>(responses);

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace Bit.Core.SecretsManager.AuthorizationRequirements;
public class BulkSecretOperationRequirement : OperationAuthorizationRequirement
{
}
public static class BulkSecretOperations
{
public static readonly BulkSecretOperationRequirement ReadAll = new() { Name = nameof(ReadAll) };
}

View File

@ -21,6 +21,7 @@ public interface ISecretRepository
Task RestoreManyByIdAsync(IEnumerable<Guid> ids);
Task<IEnumerable<Secret>> ImportAsync(IEnumerable<Secret> secrets);
Task<(bool Read, bool Write)> AccessToSecretAsync(Guid id, Guid userId, AccessClientType accessType);
Task<Dictionary<Guid, (bool Read, bool Write)>> AccessToSecretsAsync(IEnumerable<Guid> ids, Guid userId, AccessClientType accessType);
Task EmptyTrash(DateTime nowTime, uint deleteAfterThisNumberOfDays);
Task<int> GetSecretsCountByOrganizationIdAsync(Guid organizationId);
}

View File

@ -81,6 +81,12 @@ public class NoopSecretRepository : ISecretRepository
return Task.FromResult((false, false));
}
public Task<Dictionary<Guid, (bool Read, bool Write)>> AccessToSecretsAsync(IEnumerable<Guid> ids,
Guid userId, AccessClientType accessType)
{
return Task.FromResult(null as Dictionary<Guid, (bool Read, bool Write)>);
}
public Task EmptyTrash(DateTime nowTime, uint deleteAfterThisNumberOfDays)
{
return Task.FromResult(0);