2022-06-29 19:46:41 -04:00
|
|
|
|
using Bit.Core.Entities;
|
2020-10-20 02:48:10 -04:00
|
|
|
|
using Bit.Core.Enums;
|
2020-01-15 09:19:28 -05:00
|
|
|
|
using Bit.Core.Exceptions;
|
|
|
|
|
|
using Bit.Core.Repositories;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Bit.Core.Services;
|
2022-08-29 14:53:16 -04:00
|
|
|
|
|
2020-01-15 09:19:28 -05:00
|
|
|
|
public class PolicyService : IPolicyService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly IEventService _eventService;
|
|
|
|
|
|
private readonly IOrganizationRepository _organizationRepository;
|
|
|
|
|
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
|
|
|
|
|
private readonly IPolicyRepository _policyRepository;
|
|
|
|
|
|
private readonly ISsoConfigRepository _ssoConfigRepository;
|
2020-02-27 09:30:04 -05:00
|
|
|
|
private readonly IMailService _mailService;
|
2022-08-29 14:53:16 -04:00
|
|
|
|
|
2020-01-15 09:19:28 -05:00
|
|
|
|
public PolicyService(
|
|
|
|
|
|
IEventService eventService,
|
|
|
|
|
|
IOrganizationRepository organizationRepository,
|
|
|
|
|
|
IOrganizationUserRepository organizationUserRepository,
|
2020-02-27 09:30:04 -05:00
|
|
|
|
IPolicyRepository policyRepository,
|
2021-11-09 16:37:32 +01:00
|
|
|
|
ISsoConfigRepository ssoConfigRepository,
|
2020-02-27 09:30:04 -05:00
|
|
|
|
IMailService mailService)
|
2020-01-15 09:19:28 -05:00
|
|
|
|
{
|
|
|
|
|
|
_eventService = eventService;
|
|
|
|
|
|
_organizationRepository = organizationRepository;
|
|
|
|
|
|
_organizationUserRepository = organizationUserRepository;
|
|
|
|
|
|
_policyRepository = policyRepository;
|
2021-11-09 16:37:32 +01:00
|
|
|
|
_ssoConfigRepository = ssoConfigRepository;
|
2020-02-27 09:30:04 -05:00
|
|
|
|
_mailService = mailService;
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2020-01-15 09:19:28 -05:00
|
|
|
|
|
|
|
|
|
|
public async Task SaveAsync(Policy policy, IUserService userService, IOrganizationService organizationService,
|
2020-02-19 14:56:16 -05:00
|
|
|
|
Guid? savingUserId)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2020-02-27 09:30:04 -05:00
|
|
|
|
var org = await _organizationRepository.GetByIdAsync(policy.OrganizationId);
|
|
|
|
|
|
if (org == null)
|
2020-01-15 09:19:28 -05:00
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Organization not found");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-19 14:56:16 -05:00
|
|
|
|
if (!org.UsePolicies)
|
2020-01-15 09:19:28 -05:00
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("This organization cannot use policies.");
|
|
|
|
|
|
}
|
2021-12-16 15:35:09 +01:00
|
|
|
|
|
2020-10-27 14:08:19 -05:00
|
|
|
|
// Handle dependent policy checks
|
|
|
|
|
|
switch (policy.Type)
|
|
|
|
|
|
{
|
2020-12-16 16:02:54 -06:00
|
|
|
|
case PolicyType.SingleOrg:
|
|
|
|
|
|
if (!policy.Enabled)
|
|
|
|
|
|
{
|
2021-11-15 19:25:10 +10:00
|
|
|
|
await RequiredBySsoAsync(org);
|
|
|
|
|
|
await RequiredByVaultTimeoutAsync(org);
|
|
|
|
|
|
await RequiredByKeyConnectorAsync(org);
|
2020-12-16 16:02:54 -06:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2021-12-16 15:35:09 +01:00
|
|
|
|
|
2020-10-27 14:08:19 -05:00
|
|
|
|
case PolicyType.RequireSso:
|
2021-11-15 19:25:10 +10:00
|
|
|
|
if (policy.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
await DependsOnSingleOrgAsync(org);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
await RequiredByKeyConnectorAsync(org);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2021-11-08 14:37:40 +01:00
|
|
|
|
case PolicyType.MaximumVaultTimeout:
|
2020-10-27 14:08:19 -05:00
|
|
|
|
if (policy.Enabled)
|
|
|
|
|
|
{
|
2021-11-15 19:25:10 +10:00
|
|
|
|
await DependsOnSingleOrgAsync(org);
|
2020-10-27 14:08:19 -05:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2020-01-15 09:19:28 -05:00
|
|
|
|
|
2020-01-20 09:02:41 -05:00
|
|
|
|
var now = DateTime.UtcNow;
|
2020-03-27 14:36:37 -04:00
|
|
|
|
if (policy.Id == default(Guid))
|
2020-01-15 09:19:28 -05:00
|
|
|
|
{
|
2020-01-20 09:02:41 -05:00
|
|
|
|
policy.CreationDate = now;
|
2020-01-15 09:19:28 -05:00
|
|
|
|
}
|
2022-04-22 08:13:02 +10:00
|
|
|
|
|
|
|
|
|
|
if (policy.Enabled)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2020-02-19 14:56:16 -05:00
|
|
|
|
var currentPolicy = await _policyRepository.GetByIdAsync(policy.Id);
|
2020-03-27 14:36:37 -04:00
|
|
|
|
if (!currentPolicy?.Enabled ?? true)
|
2020-02-19 14:56:16 -05:00
|
|
|
|
{
|
|
|
|
|
|
var orgUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(
|
|
|
|
|
|
policy.OrganizationId);
|
2020-03-27 14:36:37 -04:00
|
|
|
|
var removableOrgUsers = orgUsers.Where(ou =>
|
|
|
|
|
|
ou.Status != Enums.OrganizationUserStatusType.Invited &&
|
|
|
|
|
|
ou.Type != Enums.OrganizationUserType.Owner && ou.Type != Enums.OrganizationUserType.Admin &&
|
2020-11-10 09:53:44 -06:00
|
|
|
|
ou.UserId != savingUserId);
|
2020-03-27 14:36:37 -04:00
|
|
|
|
switch (policy.Type)
|
2020-02-19 14:56:16 -05:00
|
|
|
|
{
|
2020-10-20 02:48:10 -04:00
|
|
|
|
case Enums.PolicyType.TwoFactorAuthentication:
|
|
|
|
|
|
foreach (var orgUser in removableOrgUsers)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2020-10-20 02:48:10 -04:00
|
|
|
|
if (!await userService.TwoFactorIsEnabledAsync(orgUser))
|
2020-02-19 14:56:16 -05:00
|
|
|
|
{
|
2020-10-20 02:48:10 -04:00
|
|
|
|
await organizationService.DeleteUserAsync(policy.OrganizationId, orgUser.Id,
|
|
|
|
|
|
savingUserId);
|
|
|
|
|
|
await _mailService.SendOrganizationUserRemovedForPolicyTwoStepEmailAsync(
|
2021-06-11 11:33:32 -04:00
|
|
|
|
org.Name, orgUser.Email);
|
2020-02-19 14:56:16 -05:00
|
|
|
|
}
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2020-10-20 02:48:10 -04:00
|
|
|
|
break;
|
2020-10-27 10:28:41 -04:00
|
|
|
|
case Enums.PolicyType.SingleOrg:
|
2020-10-20 02:48:10 -04:00
|
|
|
|
var userOrgs = await _organizationUserRepository.GetManyByManyUsersAsync(
|
|
|
|
|
|
removableOrgUsers.Select(ou => ou.UserId.Value));
|
|
|
|
|
|
foreach (var orgUser in removableOrgUsers)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2021-01-25 11:19:33 -05:00
|
|
|
|
if (userOrgs.Any(ou => ou.UserId == orgUser.UserId
|
2021-06-11 11:33:32 -04:00
|
|
|
|
&& ou.OrganizationId != org.Id
|
2021-01-25 11:19:33 -05:00
|
|
|
|
&& ou.Status != OrganizationUserStatusType.Invited))
|
2020-10-20 02:48:10 -04:00
|
|
|
|
{
|
|
|
|
|
|
await organizationService.DeleteUserAsync(policy.OrganizationId, orgUser.Id,
|
|
|
|
|
|
savingUserId);
|
2020-10-27 10:28:41 -04:00
|
|
|
|
await _mailService.SendOrganizationUserRemovedForPolicySingleOrgEmailAsync(
|
2021-06-11 11:33:32 -04:00
|
|
|
|
org.Name, orgUser.Email);
|
2020-10-20 02:48:10 -04:00
|
|
|
|
}
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2020-10-20 02:48:10 -04:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
2020-02-19 14:56:16 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-01-15 09:19:28 -05:00
|
|
|
|
}
|
2021-06-11 11:33:32 -04:00
|
|
|
|
policy.RevisionDate = now;
|
2020-01-20 09:02:41 -05:00
|
|
|
|
await _policyRepository.UpsertAsync(policy);
|
|
|
|
|
|
await _eventService.LogPolicyEventAsync(policy, Enums.EventType.Policy_Updated);
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2021-11-15 19:25:10 +10:00
|
|
|
|
|
|
|
|
|
|
private async Task DependsOnSingleOrgAsync(Organization org)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2021-11-15 19:25:10 +10:00
|
|
|
|
var singleOrg = await _policyRepository.GetByOrganizationIdTypeAsync(org.Id, PolicyType.SingleOrg);
|
|
|
|
|
|
if (singleOrg?.Enabled != true)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Single Organization policy not enabled.");
|
|
|
|
|
|
}
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2021-11-15 19:25:10 +10:00
|
|
|
|
|
|
|
|
|
|
private async Task RequiredBySsoAsync(Organization org)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2021-11-15 19:25:10 +10:00
|
|
|
|
var requireSso = await _policyRepository.GetByOrganizationIdTypeAsync(org.Id, PolicyType.RequireSso);
|
|
|
|
|
|
if (requireSso?.Enabled == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Single Sign-On Authentication policy is enabled.");
|
|
|
|
|
|
}
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2021-11-15 19:25:10 +10:00
|
|
|
|
|
|
|
|
|
|
private async Task RequiredByKeyConnectorAsync(Organization org)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(org.Id);
|
2021-11-17 11:46:35 +01:00
|
|
|
|
if (ssoConfig?.GetData()?.KeyConnectorEnabled == true)
|
2021-11-15 19:25:10 +10:00
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Key Connector is enabled.");
|
|
|
|
|
|
}
|
2022-08-29 14:53:16 -04:00
|
|
|
|
}
|
2021-11-15 19:25:10 +10:00
|
|
|
|
|
|
|
|
|
|
private async Task RequiredByVaultTimeoutAsync(Organization org)
|
2022-08-29 14:53:16 -04:00
|
|
|
|
{
|
2021-11-15 19:25:10 +10:00
|
|
|
|
var vaultTimeout = await _policyRepository.GetByOrganizationIdTypeAsync(org.Id, PolicyType.MaximumVaultTimeout);
|
|
|
|
|
|
if (vaultTimeout?.Enabled == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new BadRequestException("Maximum Vault Timeout policy is enabled.");
|
|
|
|
|
|
}
|
2020-01-15 09:19:28 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|