mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
[SM-473] Access Policies - Service Accounts (#2658)
* Add service account access policy endpoints * Add unit & integration tests for new endpoints * Fix formatting on response models * Cleanup unit tests
This commit is contained in:
@ -12,15 +12,18 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand
|
||||
private readonly IAccessPolicyRepository _accessPolicyRepository;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IServiceAccountRepository _serviceAccountRepository;
|
||||
|
||||
public CreateAccessPoliciesCommand(
|
||||
IAccessPolicyRepository accessPolicyRepository,
|
||||
ICurrentContext currentContext,
|
||||
IProjectRepository projectRepository)
|
||||
IProjectRepository projectRepository,
|
||||
IServiceAccountRepository serviceAccountRepository)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_accessPolicyRepository = accessPolicyRepository;
|
||||
_currentContext = currentContext;
|
||||
_projectRepository = projectRepository;
|
||||
_serviceAccountRepository = serviceAccountRepository;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<BaseAccessPolicy>> CreateForProjectAsync(Guid projectId,
|
||||
@ -32,21 +35,33 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var orgAdmin = await _currentContext.OrganizationAdmin(project.OrganizationId);
|
||||
var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin);
|
||||
await CheckPermissionAsync(project.OrganizationId, userId, projectId);
|
||||
CheckForDistinctAccessPolicies(accessPolicies);
|
||||
await CheckAccessPoliciesDoNotExistAsync(accessPolicies);
|
||||
|
||||
var hasAccess = accessClient switch
|
||||
{
|
||||
AccessClientType.NoAccessCheck => true,
|
||||
AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId),
|
||||
_ => false,
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
return await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(projectId);
|
||||
}
|
||||
|
||||
if (!hasAccess)
|
||||
public async Task<IEnumerable<BaseAccessPolicy>> CreateForServiceAccountAsync(Guid serviceAccountId,
|
||||
List<BaseAccessPolicy> accessPolicies, Guid userId)
|
||||
{
|
||||
var serviceAccount = await _serviceAccountRepository.GetByIdAsync(serviceAccountId);
|
||||
if (serviceAccount == null || !_currentContext.AccessSecretsManager(serviceAccount.OrganizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await CheckPermissionAsync(serviceAccount.OrganizationId, userId, serviceAccountIdToCheck: serviceAccountId);
|
||||
CheckForDistinctAccessPolicies(accessPolicies);
|
||||
await CheckAccessPoliciesDoNotExistAsync(accessPolicies);
|
||||
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
return await _accessPolicyRepository.GetManyByGrantedServiceAccountIdAsync(serviceAccountId);
|
||||
}
|
||||
|
||||
private static void CheckForDistinctAccessPolicies(IReadOnlyCollection<BaseAccessPolicy> accessPolicies)
|
||||
{
|
||||
var distinctAccessPolicies = accessPolicies.DistinctBy(baseAccessPolicy =>
|
||||
{
|
||||
return baseAccessPolicy switch
|
||||
@ -55,6 +70,9 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand
|
||||
GroupProjectAccessPolicy ap => new Tuple<Guid?, Guid?>(ap.GroupId, ap.GrantedProjectId),
|
||||
ServiceAccountProjectAccessPolicy ap => new Tuple<Guid?, Guid?>(ap.ServiceAccountId,
|
||||
ap.GrantedProjectId),
|
||||
UserServiceAccountAccessPolicy ap => new Tuple<Guid?, Guid?>(ap.OrganizationUserId,
|
||||
ap.GrantedServiceAccountId),
|
||||
GroupServiceAccountAccessPolicy ap => new Tuple<Guid?, Guid?>(ap.GroupId, ap.GrantedServiceAccountId),
|
||||
_ => throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)),
|
||||
};
|
||||
}).ToList();
|
||||
@ -63,7 +81,10 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand
|
||||
{
|
||||
throw new BadRequestException("Resources must be unique");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CheckAccessPoliciesDoNotExistAsync(List<BaseAccessPolicy> accessPolicies)
|
||||
{
|
||||
foreach (var accessPolicy in accessPolicies)
|
||||
{
|
||||
if (await _accessPolicyRepository.AccessPolicyExists(accessPolicy))
|
||||
@ -71,7 +92,46 @@ public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand
|
||||
throw new BadRequestException("Resource already exists");
|
||||
}
|
||||
}
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
return await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(projectId);
|
||||
}
|
||||
|
||||
private async Task CheckPermissionAsync(Guid organizationId,
|
||||
Guid userId,
|
||||
Guid? projectIdToCheck = null,
|
||||
Guid? serviceAccountIdToCheck = null)
|
||||
{
|
||||
var orgAdmin = await _currentContext.OrganizationAdmin(organizationId);
|
||||
var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin);
|
||||
|
||||
bool hasAccess;
|
||||
switch (accessClient)
|
||||
{
|
||||
case AccessClientType.NoAccessCheck:
|
||||
hasAccess = true;
|
||||
break;
|
||||
case AccessClientType.User:
|
||||
if (projectIdToCheck != null)
|
||||
{
|
||||
hasAccess = await _projectRepository.UserHasWriteAccessToProject(projectIdToCheck.Value, userId);
|
||||
}
|
||||
else if (serviceAccountIdToCheck != null)
|
||||
{
|
||||
hasAccess = await _serviceAccountRepository.UserHasWriteAccessToServiceAccount(
|
||||
serviceAccountIdToCheck.Value,
|
||||
userId);
|
||||
}
|
||||
else
|
||||
{
|
||||
hasAccess = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
hasAccess = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasAccess)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user