1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52:49 -05:00

[SM-707] Refactor authorization for Access Policy Commands (#2905)

* Extract authorization from access policy commands

* Use auto mapper to ignore unwanted properties

---------
This commit is contained in:
Thomas Avery
2023-07-13 11:46:01 -05:00
committed by GitHub
parent d6a45d4802
commit 1d9aeb37aa
19 changed files with 1732 additions and 1138 deletions

View File

@ -5,6 +5,7 @@ using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.SecretsManager.AuthorizationRequirements;
using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces;
using Bit.Core.SecretsManager.Entities;
using Bit.Core.SecretsManager.Repositories;
@ -31,8 +32,10 @@ public class AccessPoliciesController : Controller
private readonly IServiceAccountRepository _serviceAccountRepository;
private readonly IUpdateAccessPolicyCommand _updateAccessPolicyCommand;
private readonly IUserService _userService;
private readonly IAuthorizationService _authorizationService;
public AccessPoliciesController(
IAuthorizationService authorizationService,
IUserService userService,
ICurrentContext currentContext,
IAccessPolicyRepository accessPolicyRepository,
@ -44,6 +47,7 @@ public class AccessPoliciesController : Controller
IDeleteAccessPolicyCommand deleteAccessPolicyCommand,
IUpdateAccessPolicyCommand updateAccessPolicyCommand)
{
_authorizationService = authorizationService;
_userService = userService;
_currentContext = currentContext;
_serviceAccountRepository = serviceAccountRepository;
@ -71,9 +75,17 @@ public class AccessPoliciesController : Controller
throw new NotFoundException();
}
var (accessClient, userId) = await GetAccessClientTypeAsync(project.OrganizationId);
var policies = request.ToBaseAccessPoliciesForProject(id);
var results = await _createAccessPoliciesCommand.CreateManyAsync(policies, userId, accessClient);
var policies = request.ToBaseAccessPoliciesForProject(id, project.OrganizationId);
foreach (var policy in policies)
{
var authorizationResult = await _authorizationService.AuthorizeAsync(User, policy, AccessPolicyOperations.Create);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
}
var results = await _createAccessPoliciesCommand.CreateManyAsync(policies);
return new ProjectAccessPoliciesResponseModel(results);
}
@ -102,9 +114,17 @@ public class AccessPoliciesController : Controller
throw new NotFoundException();
}
var (accessClient, userId) = await GetAccessClientTypeAsync(serviceAccount.OrganizationId);
var policies = request.ToBaseAccessPoliciesForServiceAccount(id);
var results = await _createAccessPoliciesCommand.CreateManyAsync(policies, userId, accessClient);
var policies = request.ToBaseAccessPoliciesForServiceAccount(id, serviceAccount.OrganizationId);
foreach (var policy in policies)
{
var authorizationResult = await _authorizationService.AuthorizeAsync(User, policy, AccessPolicyOperations.Create);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
}
var results = await _createAccessPoliciesCommand.CreateManyAsync(policies);
return new ServiceAccountAccessPoliciesResponseModel(results);
}
@ -128,17 +148,29 @@ public class AccessPoliciesController : Controller
throw new BadRequestException($"Can process no more than {_maxBulkCreation} creation requests at once.");
}
if (requests.Count != requests.DistinctBy(request => request.GrantedId).Count())
{
throw new BadRequestException("Resources must be unique");
}
var serviceAccount = await _serviceAccountRepository.GetByIdAsync(id);
if (serviceAccount == null)
{
throw new NotFoundException();
}
var (accessClient, userId) = await GetAccessClientTypeAsync(serviceAccount.OrganizationId);
var policies = requests.Select(request => request.ToServiceAccountProjectAccessPolicy(id));
var policies = requests.Select(request => request.ToServiceAccountProjectAccessPolicy(id, serviceAccount.OrganizationId)).ToList();
foreach (var policy in policies)
{
var authorizationResult = await _authorizationService.AuthorizeAsync(User, policy, AccessPolicyOperations.Create);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
}
var results =
await _createAccessPoliciesCommand.CreateManyAsync(new List<BaseAccessPolicy>(policies), userId,
accessClient);
await _createAccessPoliciesCommand.CreateManyAsync(new List<BaseAccessPolicy>(policies));
var responses = results.Select(ap =>
new ServiceAccountProjectAccessPolicyResponseModel((ServiceAccountProjectAccessPolicy)ap));
return new ListResponseModel<ServiceAccountProjectAccessPolicyResponseModel>(responses);
@ -165,8 +197,15 @@ public class AccessPoliciesController : Controller
public async Task<BaseAccessPolicyResponseModel> UpdateAccessPolicyAsync([FromRoute] Guid id,
[FromBody] AccessPolicyUpdateRequest request)
{
var userId = _userService.GetProperUserId(User).Value;
var result = await _updateAccessPolicyCommand.UpdateAsync(id, request.Read, request.Write, userId);
var ap = await _accessPolicyRepository.GetByIdAsync(id);
var authorizationResult =
await _authorizationService.AuthorizeAsync(User, ap, AccessPolicyOperations.Update);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
var result = await _updateAccessPolicyCommand.UpdateAsync(id, request.Read, request.Write);
return result switch
{
@ -185,8 +224,15 @@ public class AccessPoliciesController : Controller
[HttpDelete("{id}")]
public async Task DeleteAccessPolicyAsync([FromRoute] Guid id)
{
var userId = _userService.GetProperUserId(User).Value;
await _deleteAccessPolicyCommand.DeleteAsync(id, userId);
var ap = await _accessPolicyRepository.GetByIdAsync(id);
var authorizationResult =
await _authorizationService.AuthorizeAsync(User, ap, AccessPolicyOperations.Delete);
if (!authorizationResult.Succeeded)
{
throw new NotFoundException();
}
await _deleteAccessPolicyCommand.DeleteAsync(id);
}
[HttpGet("/organizations/{id}/access-policies/people/potential-grantees")]