1
0
mirror of https://github.com/bitwarden/server synced 2026-01-17 07:53:36 +00:00

[PM-28485] Move organization events domain to DIRT code ownership (#6685)

This commit is contained in:
Thomas Rittson
2025-12-20 07:32:51 +10:00
committed by GitHub
parent bc800a788e
commit 69d72c2ad3
52 changed files with 15 additions and 13 deletions

View File

@@ -1,68 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
#nullable enable
namespace Bit.Core.Entities;
public class Event : ITableObject<Guid>, IEvent
{
public Event() { }
public Event(IEvent e)
{
Date = e.Date;
Type = e.Type;
UserId = e.UserId;
OrganizationId = e.OrganizationId;
ProviderId = e.ProviderId;
CipherId = e.CipherId;
CollectionId = e.CollectionId;
PolicyId = e.PolicyId;
GroupId = e.GroupId;
OrganizationUserId = e.OrganizationUserId;
InstallationId = e.InstallationId;
ProviderUserId = e.ProviderUserId;
ProviderOrganizationId = e.ProviderOrganizationId;
DeviceType = e.DeviceType;
IpAddress = e.IpAddress;
ActingUserId = e.ActingUserId;
SystemUser = e.SystemUser;
DomainName = e.DomainName;
SecretId = e.SecretId;
ProjectId = e.ProjectId;
ServiceAccountId = e.ServiceAccountId;
GrantedServiceAccountId = e.GrantedServiceAccountId;
}
public Guid Id { get; set; }
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public DeviceType? DeviceType { get; set; }
[MaxLength(50)]
public string? IpAddress { get; set; }
public Guid? ActingUserId { get; set; }
public EventSystemUser? SystemUser { get; set; }
public string? DomainName { get; set; }
public Guid? SecretId { get; set; }
public Guid? ProjectId { get; set; }
public Guid? ServiceAccountId { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
public void SetNewId()
{
Id = CoreHelpers.GenerateComb();
}
}

View File

@@ -1,10 +0,0 @@
namespace Bit.Core.Enums;
public enum EventSystemUser : byte
{
Unknown = 0,
SCIM = 1,
DomainVerification = 2,
PublicApi = 3,
TwoFactorDisabled = 4,
}

View File

@@ -1,122 +0,0 @@
namespace Bit.Core.Enums;
// Increment by 100 for each new set of events
public enum EventType : int
{
User_LoggedIn = 1000,
User_ChangedPassword = 1001,
User_Updated2fa = 1002,
User_Disabled2fa = 1003,
User_Recovered2fa = 1004,
User_FailedLogIn = 1005,
User_FailedLogIn2fa = 1006,
User_ClientExportedVault = 1007,
User_UpdatedTempPassword = 1008,
User_MigratedKeyToKeyConnector = 1009,
User_RequestedDeviceApproval = 1010,
User_TdeOffboardingPasswordSet = 1011,
Cipher_Created = 1100,
Cipher_Updated = 1101,
Cipher_Deleted = 1102,
Cipher_AttachmentCreated = 1103,
Cipher_AttachmentDeleted = 1104,
Cipher_Shared = 1105,
Cipher_UpdatedCollections = 1106,
Cipher_ClientViewed = 1107,
Cipher_ClientToggledPasswordVisible = 1108,
Cipher_ClientToggledHiddenFieldVisible = 1109,
Cipher_ClientToggledCardCodeVisible = 1110,
Cipher_ClientCopiedPassword = 1111,
Cipher_ClientCopiedHiddenField = 1112,
Cipher_ClientCopiedCardCode = 1113,
Cipher_ClientAutofilled = 1114,
Cipher_SoftDeleted = 1115,
Cipher_Restored = 1116,
Cipher_ClientToggledCardNumberVisible = 1117,
Collection_Created = 1300,
Collection_Updated = 1301,
Collection_Deleted = 1302,
Group_Created = 1400,
Group_Updated = 1401,
Group_Deleted = 1402,
OrganizationUser_Invited = 1500,
OrganizationUser_Confirmed = 1501,
OrganizationUser_Updated = 1502,
OrganizationUser_Removed = 1503, // Organization user data was deleted
OrganizationUser_UpdatedGroups = 1504,
OrganizationUser_UnlinkedSso = 1505,
OrganizationUser_ResetPassword_Enroll = 1506,
OrganizationUser_ResetPassword_Withdraw = 1507,
OrganizationUser_AdminResetPassword = 1508,
OrganizationUser_ResetSsoLink = 1509,
OrganizationUser_FirstSsoLogin = 1510,
OrganizationUser_Revoked = 1511,
OrganizationUser_Restored = 1512,
OrganizationUser_ApprovedAuthRequest = 1513,
OrganizationUser_RejectedAuthRequest = 1514,
OrganizationUser_Deleted = 1515, // Both user and organization user data were deleted
OrganizationUser_Left = 1516, // User voluntarily left the organization
OrganizationUser_AutomaticallyConfirmed = 1517,
Organization_Updated = 1600,
Organization_PurgedVault = 1601,
Organization_ClientExportedVault = 1602,
Organization_VaultAccessed = 1603,
Organization_EnabledSso = 1604,
Organization_DisabledSso = 1605,
Organization_EnabledKeyConnector = 1606,
Organization_DisabledKeyConnector = 1607,
Organization_SponsorshipsSynced = 1608,
[Obsolete("Kept for historical data. Use specific Organization_CollectionManagement events instead.")]
Organization_CollectionManagement_Updated = 1609,
Organization_CollectionManagement_LimitCollectionCreationEnabled = 1610,
Organization_CollectionManagement_LimitCollectionCreationDisabled = 1611,
Organization_CollectionManagement_LimitCollectionDeletionEnabled = 1612,
Organization_CollectionManagement_LimitCollectionDeletionDisabled = 1613,
Organization_CollectionManagement_LimitItemDeletionEnabled = 1614,
Organization_CollectionManagement_LimitItemDeletionDisabled = 1615,
Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled = 1616,
Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsDisabled = 1617,
Organization_ItemOrganization_Accepted = 1618,
Organization_ItemOrganization_Declined = 1619,
Policy_Updated = 1700,
ProviderUser_Invited = 1800,
ProviderUser_Confirmed = 1801,
ProviderUser_Updated = 1802,
ProviderUser_Removed = 1803,
ProviderOrganization_Created = 1900,
ProviderOrganization_Added = 1901,
ProviderOrganization_Removed = 1902,
ProviderOrganization_VaultAccessed = 1903,
OrganizationDomain_Added = 2000,
OrganizationDomain_Removed = 2001,
OrganizationDomain_Verified = 2002,
OrganizationDomain_NotVerified = 2003,
Secret_Retrieved = 2100,
Secret_Created = 2101,
Secret_Edited = 2102,
Secret_Deleted = 2103,
Secret_Permanently_Deleted = 2104,
Secret_Restored = 2105,
Project_Retrieved = 2200,
Project_Created = 2201,
Project_Edited = 2202,
Project_Deleted = 2203,
ServiceAccount_UserAdded = 2300,
ServiceAccount_UserRemoved = 2301,
ServiceAccount_GroupAdded = 2302,
ServiceAccount_GroupRemoved = 2303,
ServiceAccount_Created = 2304,
ServiceAccount_Deleted = 2305,
}

View File

@@ -1,43 +0,0 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Bit.Core.Context;
using Bit.Core.Enums;
namespace Bit.Core.Models.Data;
public class EventMessage : IEvent
{
public EventMessage() { }
public EventMessage(ICurrentContext currentContext)
: base()
{
IpAddress = currentContext.IpAddress;
DeviceType = currentContext.DeviceType;
}
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? GroupId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public Guid? ActingUserId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? IdempotencyId { get; private set; } = Guid.NewGuid();
public EventSystemUser? SystemUser { get; set; }
public string DomainName { get; set; }
public Guid? SecretId { get; set; }
public Guid? ProjectId { get; set; }
public Guid? ServiceAccountId { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
}

View File

@@ -1,266 +0,0 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Azure;
using Azure.Data.Tables;
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data;
// used solely for interaction with Azure Table Storage
public class AzureEvent : ITableEntity
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
public DateTime Date { get; set; }
public int Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public int? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? ActingUserId { get; set; }
public int? SystemUser { get; set; }
public string DomainName { get; set; }
public Guid? SecretId { get; set; }
public Guid? ProjectId { get; set; }
public Guid? ServiceAccountId { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
public EventTableEntity ToEventTableEntity()
{
return new EventTableEntity
{
PartitionKey = PartitionKey,
RowKey = RowKey,
Timestamp = Timestamp,
ETag = ETag,
Date = Date,
Type = (EventType)Type,
UserId = UserId,
OrganizationId = OrganizationId,
InstallationId = InstallationId,
ProviderId = ProviderId,
CipherId = CipherId,
CollectionId = CollectionId,
PolicyId = PolicyId,
GroupId = GroupId,
OrganizationUserId = OrganizationUserId,
ProviderUserId = ProviderUserId,
ProviderOrganizationId = ProviderOrganizationId,
DeviceType = DeviceType.HasValue ? (DeviceType)DeviceType.Value : null,
IpAddress = IpAddress,
ActingUserId = ActingUserId,
SystemUser = SystemUser.HasValue ? (EventSystemUser)SystemUser.Value : null,
DomainName = DomainName,
SecretId = SecretId,
ServiceAccountId = ServiceAccountId,
ProjectId = ProjectId,
GrantedServiceAccountId = GrantedServiceAccountId
};
}
}
public class EventTableEntity : IEvent
{
public EventTableEntity() { }
private EventTableEntity(IEvent e)
{
Date = e.Date;
Type = e.Type;
UserId = e.UserId;
OrganizationId = e.OrganizationId;
InstallationId = e.InstallationId;
ProviderId = e.ProviderId;
CipherId = e.CipherId;
CollectionId = e.CollectionId;
PolicyId = e.PolicyId;
GroupId = e.GroupId;
OrganizationUserId = e.OrganizationUserId;
ProviderUserId = e.ProviderUserId;
ProviderOrganizationId = e.ProviderOrganizationId;
DeviceType = e.DeviceType;
IpAddress = e.IpAddress;
ActingUserId = e.ActingUserId;
SystemUser = e.SystemUser;
DomainName = e.DomainName;
SecretId = e.SecretId;
ProjectId = e.ProjectId;
ServiceAccountId = e.ServiceAccountId;
GrantedServiceAccountId = e.GrantedServiceAccountId;
}
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? ActingUserId { get; set; }
public EventSystemUser? SystemUser { get; set; }
public string DomainName { get; set; }
public Guid? SecretId { get; set; }
public Guid? ProjectId { get; set; }
public Guid? ServiceAccountId { get; set; }
public Guid? GrantedServiceAccountId { get; set; }
public AzureEvent ToAzureEvent()
{
return new AzureEvent
{
PartitionKey = PartitionKey,
RowKey = RowKey,
Timestamp = Timestamp,
ETag = ETag,
Date = Date,
Type = (int)Type,
UserId = UserId,
OrganizationId = OrganizationId,
InstallationId = InstallationId,
ProviderId = ProviderId,
CipherId = CipherId,
CollectionId = CollectionId,
PolicyId = PolicyId,
GroupId = GroupId,
OrganizationUserId = OrganizationUserId,
ProviderUserId = ProviderUserId,
ProviderOrganizationId = ProviderOrganizationId,
DeviceType = DeviceType.HasValue ? (int)DeviceType.Value : null,
IpAddress = IpAddress,
ActingUserId = ActingUserId,
SystemUser = SystemUser.HasValue ? (int)SystemUser.Value : null,
DomainName = DomainName,
SecretId = SecretId,
ProjectId = ProjectId,
ServiceAccountId = ServiceAccountId,
GrantedServiceAccountId = GrantedServiceAccountId
};
}
public static List<EventTableEntity> IndexEvent(EventMessage e)
{
var uniquifier = e.IdempotencyId.GetValueOrDefault(Guid.NewGuid());
var pKey = GetPartitionKey(e);
var dateKey = CoreHelpers.DateTimeToTableStorageKey(e.Date);
var entities = new List<EventTableEntity>
{
new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"Date={dateKey}__Uniquifier={uniquifier}"
}
};
if (e.OrganizationId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (!e.OrganizationId.HasValue && e.ProviderId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.CipherId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"CipherId={e.CipherId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.OrganizationId.HasValue && e.ServiceAccountId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ServiceAccountId={e.ServiceAccountId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.SecretId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"SecretId={e.SecretId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.ProjectId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ProjectId={e.ProjectId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.GrantedServiceAccountId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"GrantedServiceAccountId={e.GrantedServiceAccountId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
return entities;
}
private static string GetPartitionKey(EventMessage e)
{
if (e.OrganizationId.HasValue)
{
return $"OrganizationId={e.OrganizationId}";
}
if (e.ProviderId.HasValue)
{
return $"ProviderId={e.ProviderId}";
}
return $"UserId={e.UserId}";
}
}

View File

@@ -1,32 +0,0 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Bit.Core.Enums;
namespace Bit.Core.Models.Data;
public interface IEvent
{
EventType Type { get; set; }
Guid? UserId { get; set; }
Guid? OrganizationId { get; set; }
Guid? InstallationId { get; set; }
Guid? ProviderId { get; set; }
Guid? CipherId { get; set; }
Guid? CollectionId { get; set; }
Guid? GroupId { get; set; }
Guid? PolicyId { get; set; }
Guid? OrganizationUserId { get; set; }
Guid? ProviderUserId { get; set; }
Guid? ProviderOrganizationId { get; set; }
Guid? ActingUserId { get; set; }
DeviceType? DeviceType { get; set; }
string IpAddress { get; set; }
DateTime Date { get; set; }
EventSystemUser? SystemUser { get; set; }
string DomainName { get; set; }
Guid? SecretId { get; set; }
Guid? ProjectId { get; set; }
Guid? ServiceAccountId { get; set; }
Guid? GrantedServiceAccountId { get; set; }
}

View File

@@ -1,35 +0,0 @@
using Bit.Core.Models.Data;
using Bit.Core.SecretsManager.Entities;
using Bit.Core.Vault.Entities;
#nullable enable
namespace Bit.Core.Repositories;
public interface IEventRepository
{
Task<PagedResult<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByOrganizationAsync(Guid organizationId, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyBySecretAsync(Secret secret, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByProjectAsync(Project project, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByOrganizationActingUserAsync(Guid organizationId, Guid actingUserId,
DateTime startDate, DateTime endDate, PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByProviderAsync(Guid providerId, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByProviderActingUserAsync(Guid providerId, Guid actingUserId,
DateTime startDate, DateTime endDate, PageOptions pageOptions);
Task<PagedResult<IEvent>> GetManyByCipherAsync(Cipher cipher, DateTime startDate, DateTime endDate,
PageOptions pageOptions);
Task CreateAsync(IEvent e);
Task CreateManyAsync(IEnumerable<IEvent> e);
Task<PagedResult<IEvent>> GetManyByOrganizationServiceAccountAsync(Guid organizationId, Guid serviceAccountId,
DateTime startDate, DateTime endDate, PageOptions pageOptions);
}

View File

@@ -1,238 +0,0 @@
using Azure.Data.Tables;
using Bit.Core.Models.Data;
using Bit.Core.SecretsManager.Entities;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Bit.Core.Vault.Entities;
#nullable enable
namespace Bit.Core.Repositories.TableStorage;
public class EventRepository : IEventRepository
{
private readonly TableClient _tableClient;
public EventRepository(GlobalSettings globalSettings)
: this(globalSettings.Events.ConnectionString)
{ }
public EventRepository(string storageConnectionString)
{
var tableClient = new TableServiceClient(storageConnectionString);
_tableClient = tableClient.GetTableClient("event");
}
public async Task<PagedResult<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate,
PageOptions pageOptions)
{
return await GetManyAsync($"UserId={userId}", "Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByOrganizationAsync(Guid organizationId,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"OrganizationId={organizationId}", "Date={0}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyBySecretAsync(Secret secret,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"OrganizationId={secret.OrganizationId}",
$"SecretId={secret.Id}__Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByProjectAsync(Project project,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"OrganizationId={project.OrganizationId}",
$"ProjectId={project.Id}__Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByOrganizationActingUserAsync(Guid organizationId, Guid actingUserId,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"OrganizationId={organizationId}",
$"ActingUserId={actingUserId}__Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByProviderAsync(Guid providerId,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"ProviderId={providerId}", "Date={0}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByProviderActingUserAsync(Guid providerId, Guid actingUserId,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
return await GetManyAsync($"ProviderId={providerId}",
$"ActingUserId={actingUserId}__Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByCipherAsync(Cipher cipher, DateTime startDate, DateTime endDate,
PageOptions pageOptions)
{
var partitionKey = cipher.OrganizationId.HasValue ?
$"OrganizationId={cipher.OrganizationId}" : $"UserId={cipher.UserId}";
return await GetManyAsync(partitionKey, $"CipherId={cipher.Id}__Date={{0}}", startDate, endDate, pageOptions);
}
public async Task<PagedResult<IEvent>> GetManyByOrganizationServiceAccountAsync(
Guid organizationId,
Guid serviceAccountId,
DateTime startDate,
DateTime endDate,
PageOptions pageOptions)
{
return await GetManyServiceAccountAsync(
$"OrganizationId={organizationId}",
serviceAccountId.ToString(),
startDate, endDate, pageOptions);
}
public async Task CreateAsync(IEvent e)
{
if (!(e is EventTableEntity entity))
{
throw new ArgumentException(nameof(e));
}
await CreateEventAsync(entity);
}
public async Task CreateManyAsync(IEnumerable<IEvent>? e)
{
if (e is null || !e.Any())
{
return;
}
if (!e.Skip(1).Any())
{
await CreateAsync(e.First());
return;
}
var entities = e.OfType<EventTableEntity>();
var entityGroups = entities.GroupBy(ent => ent.PartitionKey);
foreach (var group in entityGroups)
{
var groupEntities = group.ToList();
if (groupEntities.Count == 1)
{
await CreateEventAsync(groupEntities.First());
continue;
}
// A batch insert can only contain 100 entities at a time
var iterations = groupEntities.Count / 100;
for (var i = 0; i <= iterations; i++)
{
var batch = new List<TableTransactionAction>();
var batchEntities = groupEntities.Skip(i * 100).Take(100);
if (!batchEntities.Any())
{
break;
}
foreach (var entity in batchEntities)
{
batch.Add(new TableTransactionAction(TableTransactionActionType.Add,
entity.ToAzureEvent()));
}
await _tableClient.SubmitTransactionAsync(batch);
}
}
}
public async Task<PagedResult<IEvent>> GetManyServiceAccountAsync(
string partitionKey,
string serviceAccountId,
DateTime startDate,
DateTime endDate,
PageOptions pageOptions)
{
var start = CoreHelpers.DateTimeToTableStorageKey(startDate);
var end = CoreHelpers.DateTimeToTableStorageKey(endDate);
var filter = MakeFilterForServiceAccount(partitionKey, serviceAccountId, startDate, endDate);
var result = new PagedResult<IEvent>();
var query = _tableClient.QueryAsync<AzureEvent>(filter, pageOptions.PageSize);
await using (var enumerator = query.AsPages(pageOptions.ContinuationToken,
pageOptions.PageSize).GetAsyncEnumerator())
{
if (await enumerator.MoveNextAsync())
{
result.ContinuationToken = enumerator.Current.ContinuationToken;
var events = enumerator.Current.Values
.Select(e => e.ToEventTableEntity())
.ToList();
events = events.OrderByDescending(e => e.Date).ToList();
result.Data.AddRange(events);
}
}
return result;
}
public async Task<PagedResult<IEvent>> GetManyAsync(string partitionKey, string rowKey,
DateTime startDate, DateTime endDate, PageOptions pageOptions)
{
var start = CoreHelpers.DateTimeToTableStorageKey(startDate);
var end = CoreHelpers.DateTimeToTableStorageKey(endDate);
var filter = MakeFilter(partitionKey, string.Format(rowKey, start), string.Format(rowKey, end));
var result = new PagedResult<IEvent>();
var query = _tableClient.QueryAsync<AzureEvent>(filter, pageOptions.PageSize);
await using (var enumerator = query.AsPages(pageOptions.ContinuationToken,
pageOptions.PageSize).GetAsyncEnumerator())
{
await enumerator.MoveNextAsync();
result.ContinuationToken = enumerator.Current.ContinuationToken;
result.Data.AddRange(enumerator.Current.Values.Select(e => e.ToEventTableEntity()));
}
return result;
}
private async Task CreateEventAsync(EventTableEntity entity)
{
await _tableClient.UpsertEntityAsync(entity.ToAzureEvent());
}
private string MakeFilter(string partitionKey, string rowStart, string rowEnd)
{
return $"PartitionKey eq '{partitionKey}' and RowKey le '{rowStart}' and RowKey ge '{rowEnd}'";
}
private string MakeFilterForServiceAccount(
string partitionKey,
string machineAccountId,
DateTime startDate,
DateTime endDate)
{
var start = CoreHelpers.DateTimeToTableStorageKey(startDate);
var end = CoreHelpers.DateTimeToTableStorageKey(endDate);
var rowKey1Start = $"ServiceAccountId={machineAccountId}__Date={start}";
var rowKey1End = $"ServiceAccountId={machineAccountId}__Date={end}";
var rowKey2Start = $"GrantedServiceAccountId={machineAccountId}__Date={start}";
var rowKey2End = $"GrantedServiceAccountId={machineAccountId}__Date={end}";
var left = $"PartitionKey eq '{partitionKey}' and RowKey le '{rowKey1Start}' and RowKey ge '{rowKey1End}'";
var right = $"PartitionKey eq '{partitionKey}' and RowKey le '{rowKey2Start}' and RowKey ge '{rowKey2End}'";
return $"({left}) or ({right})";
}
}

View File

@@ -1,9 +0,0 @@
using Bit.Core.Models.Data;
namespace Bit.Core.Services;
public interface IEventWriteService
{
Task CreateAsync(IEvent e);
Task CreateManyAsync(IEnumerable<IEvent> e);
}

View File

@@ -1,16 +0,0 @@
using Azure.Storage.Queues;
using Bit.Core.Models.Data;
using Bit.Core.Settings;
using Bit.Core.Utilities;
namespace Bit.Core.Services;
public class AzureQueueEventWriteService : AzureQueueService<IEvent>, IEventWriteService
{
public AzureQueueEventWriteService(GlobalSettings globalSettings) : base(
new QueueClient(globalSettings.Events.ConnectionString, globalSettings.Events.QueueName),
JsonHelpers.IgnoreWritingNull)
{ }
public Task CreateAsync(IEvent e) => CreateManyAsync(new[] { e });
}

View File

@@ -1,36 +0,0 @@
using System.Text.Json;
using Bit.Core.Models.Data;
namespace Bit.Core.Services;
public class EventIntegrationEventWriteService : IEventWriteService, IAsyncDisposable
{
private readonly IEventIntegrationPublisher _eventIntegrationPublisher;
public EventIntegrationEventWriteService(IEventIntegrationPublisher eventIntegrationPublisher)
{
_eventIntegrationPublisher = eventIntegrationPublisher;
}
public async Task CreateAsync(IEvent e)
{
var body = JsonSerializer.Serialize(e);
await _eventIntegrationPublisher.PublishEventAsync(body: body, organizationId: e.OrganizationId?.ToString());
}
public async Task CreateManyAsync(IEnumerable<IEvent> events)
{
var eventList = events as IList<IEvent> ?? events.ToList();
if (eventList.Count == 0)
{
return;
}
var organizationId = eventList[0].OrganizationId?.ToString();
var body = JsonSerializer.Serialize(eventList);
await _eventIntegrationPublisher.PublishEventAsync(body: body, organizationId: organizationId);
}
public async ValueTask DisposeAsync()
{
await _eventIntegrationPublisher.DisposeAsync();
}
}

View File

@@ -1,680 +0,0 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Interfaces;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Auth.Identity;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations;
using Bit.Core.Repositories;
using Bit.Core.SecretsManager.Entities;
using Bit.Core.Settings;
using Bit.Core.Vault.Entities;
namespace Bit.Core.Services;
public class EventService : IEventService
{
private readonly IEventWriteService _eventWriteService;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IProviderUserRepository _providerUserRepository;
private readonly IApplicationCacheService _applicationCacheService;
private readonly ICurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;
public EventService(
IEventWriteService eventWriteService,
IOrganizationUserRepository organizationUserRepository,
IProviderUserRepository providerUserRepository,
IApplicationCacheService applicationCacheService,
ICurrentContext currentContext,
GlobalSettings globalSettings)
{
_eventWriteService = eventWriteService;
_organizationUserRepository = organizationUserRepository;
_providerUserRepository = providerUserRepository;
_applicationCacheService = applicationCacheService;
_currentContext = currentContext;
_globalSettings = globalSettings;
}
public async Task LogUserEventAsync(Guid userId, EventType type, DateTime? date = null)
{
var events = new List<IEvent>
{
new EventMessage(_currentContext)
{
UserId = userId,
ActingUserId = userId,
Type = type,
Date = date.GetValueOrDefault(DateTime.UtcNow)
}
};
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, userId);
var orgEvents = orgs.Where(o => CanUseEvents(orgAbilities, o.Id))
.Select(o => new EventMessage(_currentContext)
{
OrganizationId = o.Id,
UserId = userId,
ActingUserId = userId,
Type = type,
Date = DateTime.UtcNow
});
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync();
var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, userId);
var providerEvents = providers.Where(o => CanUseProviderEvents(providerAbilities, o.Id))
.Select(p => new EventMessage(_currentContext)
{
ProviderId = p.Id,
UserId = userId,
ActingUserId = userId,
Type = type,
Date = DateTime.UtcNow
});
if (orgEvents.Any() || providerEvents.Any())
{
events.AddRange(orgEvents);
events.AddRange(providerEvents);
await _eventWriteService.CreateManyAsync(events);
}
else
{
await _eventWriteService.CreateAsync(events.First());
}
}
public async Task LogCipherEventAsync(Cipher cipher, EventType type, DateTime? date = null)
{
var e = await BuildCipherEventMessageAsync(cipher, type, date);
if (e != null)
{
await _eventWriteService.CreateAsync(e);
}
}
public async Task LogCipherEventsAsync(IEnumerable<Tuple<Cipher, EventType, DateTime?>> events)
{
var cipherEvents = new List<IEvent>();
foreach (var ev in events)
{
var e = await BuildCipherEventMessageAsync(ev.Item1, ev.Item2, ev.Item3);
if (e != null)
{
cipherEvents.Add(e);
}
}
await _eventWriteService.CreateManyAsync(cipherEvents);
}
private async Task<EventMessage> BuildCipherEventMessageAsync(Cipher cipher, EventType type, DateTime? date = null)
{
// Only logging organization cipher events for now.
if (!cipher.OrganizationId.HasValue || (!_currentContext?.UserId.HasValue ?? true))
{
return null;
}
if (cipher.OrganizationId.HasValue)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
if (!CanUseEvents(orgAbilities, cipher.OrganizationId.Value))
{
return null;
}
}
return new EventMessage(_currentContext)
{
OrganizationId = cipher.OrganizationId,
UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId,
CipherId = cipher.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
ProviderId = await GetProviderIdAsync(cipher.OrganizationId),
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
}
public async Task LogCollectionEventAsync(Collection collection, EventType type, DateTime? date = null) =>
await LogCollectionEventsAsync(new[] { (collection, type, date) });
public async Task LogCollectionEventsAsync(IEnumerable<(Collection collection, EventType type, DateTime? date)> events)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var (collection, type, date) in events)
{
if (!CanUseEvents(orgAbilities, collection.OrganizationId))
{
continue;
}
eventMessages.Add(new EventMessage(_currentContext)
{
OrganizationId = collection.OrganizationId,
CollectionId = collection.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
ProviderId = await GetProviderIdAsync(collection.OrganizationId),
Date = date.GetValueOrDefault(DateTime.UtcNow)
});
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogGroupEventAsync(Group group, EventType type, DateTime? date = null) =>
await LogGroupEventsAsync(new[] { (group, type, (EventSystemUser?)null, date) });
public async Task LogGroupEventAsync(Group group, EventType type, EventSystemUser systemUser, DateTime? date = null) =>
await LogGroupEventsAsync(new[] { (group, type, (EventSystemUser?)systemUser, date) });
public async Task LogGroupEventsAsync(IEnumerable<(Group group, EventType type, EventSystemUser? systemUser, DateTime? date)> events)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var (group, type, systemUser, date) in events)
{
if (!CanUseEvents(orgAbilities, group.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = group.OrganizationId,
GroupId = group.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
ProviderId = await GetProviderIdAsync(group.OrganizationId),
SystemUser = systemUser,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
if (systemUser is EventSystemUser.SCIM)
{
// System user only used for SCIM logs in this method
// and we want event logs to report server instead of unknown
e.DeviceType = DeviceType.Server;
}
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogPolicyEventAsync(Policy policy, EventType type, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
if (!CanUseEvents(orgAbilities, policy.OrganizationId))
{
return;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = policy.OrganizationId,
PolicyId = policy.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
ProviderId = await GetProviderIdAsync(policy.OrganizationId),
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
await _eventWriteService.CreateAsync(e);
}
public async Task LogOrganizationUserEventAsync<T>(T organizationUser, EventType type,
DateTime? date = null) where T : IOrganizationUser =>
await CreateLogOrganizationUserEventsAsync(new (T, EventType, EventSystemUser?, DateTime?)[] { (organizationUser, type, null, date) });
public async Task LogOrganizationUserEventAsync<T>(T organizationUser, EventType type,
EventSystemUser systemUser, DateTime? date = null) where T : IOrganizationUser =>
await CreateLogOrganizationUserEventsAsync(new (T, EventType, EventSystemUser?, DateTime?)[] { (organizationUser, type, systemUser, date) });
public async Task LogOrganizationUserEventsAsync<T>(
IEnumerable<(T, EventType, DateTime?)> events) where T : IOrganizationUser
{
await CreateLogOrganizationUserEventsAsync(events.Select(e => (e.Item1, e.Item2, (EventSystemUser?)null, e.Item3)));
}
public async Task LogOrganizationUserEventsAsync<T>(
IEnumerable<(T, EventType, EventSystemUser, DateTime?)> events) where T : IOrganizationUser
{
await CreateLogOrganizationUserEventsAsync(events.Select(e => (e.Item1, e.Item2, (EventSystemUser?)e.Item3, e.Item4)));
}
private async Task CreateLogOrganizationUserEventsAsync<T>(IEnumerable<(T, EventType, EventSystemUser?, DateTime?)> events) where T : IOrganizationUser
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var (organizationUser, type, systemUser, date) in events)
{
if (!CanUseEvents(orgAbilities, organizationUser.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = organizationUser.OrganizationId,
UserId = organizationUser.UserId,
OrganizationUserId = organizationUser.Id,
ProviderId = await GetProviderIdAsync(organizationUser.OrganizationId),
Type = type,
ActingUserId = _currentContext?.UserId,
Date = date.GetValueOrDefault(DateTime.UtcNow),
SystemUser = systemUser
};
if (systemUser is EventSystemUser.SCIM)
{
// System user only used for SCIM logs in this method
// and we want event logs to report server instead of unknown
e.DeviceType = DeviceType.Server;
}
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogOrganizationEventAsync(Organization organization, EventType type, DateTime? date = null)
{
if (!organization.Enabled || !organization.UseEvents)
{
return;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = organization.Id,
ProviderId = await GetProviderIdAsync(organization.Id),
Type = type,
ActingUserId = _currentContext?.UserId,
Date = date.GetValueOrDefault(DateTime.UtcNow),
InstallationId = GetInstallationId(),
};
await _eventWriteService.CreateAsync(e);
}
public async Task LogProviderUserEventAsync(ProviderUser providerUser, EventType type, DateTime? date = null)
{
await LogProviderUsersEventAsync(new[] { (providerUser, type, date) });
}
public async Task LogProviderUsersEventAsync(IEnumerable<(ProviderUser, EventType, DateTime?)> events)
{
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var (providerUser, type, date) in events)
{
if (!CanUseProviderEvents(providerAbilities, providerUser.ProviderId))
{
continue;
}
eventMessages.Add(new EventMessage(_currentContext)
{
ProviderId = providerUser.ProviderId,
UserId = providerUser.UserId,
ProviderUserId = providerUser.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
});
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogProviderOrganizationEventAsync(ProviderOrganization providerOrganization, EventType type,
DateTime? date = null)
{
await LogProviderOrganizationEventsAsync(new[] { (providerOrganization, type, date) });
}
public async Task LogProviderOrganizationEventsAsync(IEnumerable<(ProviderOrganization, EventType, DateTime?)> events)
{
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var (providerOrganization, type, date) in events)
{
if (!CanUseProviderEvents(providerAbilities, providerOrganization.ProviderId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
ProviderId = providerOrganization.ProviderId,
ProviderOrganizationId = providerOrganization.Id,
Type = type,
ActingUserId = _currentContext?.UserId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogOrganizationDomainEventAsync(OrganizationDomain organizationDomain, EventType type,
DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
if (!CanUseEvents(orgAbilities, organizationDomain.OrganizationId))
{
return;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = organizationDomain.OrganizationId,
Type = type,
ActingUserId = _currentContext?.UserId,
DomainName = organizationDomain.DomainName,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
await _eventWriteService.CreateAsync(e);
}
public async Task LogOrganizationDomainEventAsync(OrganizationDomain organizationDomain, EventType type,
EventSystemUser systemUser,
DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
if (!CanUseEvents(orgAbilities, organizationDomain.OrganizationId))
{
return;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = organizationDomain.OrganizationId,
Type = type,
ActingUserId = _currentContext?.UserId,
DomainName = organizationDomain.DomainName,
SystemUser = systemUser,
Date = date.GetValueOrDefault(DateTime.UtcNow),
DeviceType = DeviceType.Server
};
await _eventWriteService.CreateAsync(e);
}
public async Task LogUserSecretsEventAsync(Guid userId, IEnumerable<Secret> secrets, EventType type, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var secret in secrets)
{
if (!CanUseEvents(orgAbilities, secret.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = secret.OrganizationId,
Type = type,
SecretId = secret.Id,
UserId = userId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogServiceAccountSecretsEventAsync(Guid serviceAccountId, IEnumerable<Secret> secrets, EventType type, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var secret in secrets)
{
if (!CanUseEvents(orgAbilities, secret.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = secret.OrganizationId,
Type = type,
SecretId = secret.Id,
ServiceAccountId = serviceAccountId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogUserProjectsEventAsync(Guid userId, IEnumerable<Project> projects, EventType type, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var project in projects)
{
if (!CanUseEvents(orgAbilities, project.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = project.OrganizationId,
Type = type,
ProjectId = project.Id,
UserId = userId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogServiceAccountProjectsEventAsync(Guid serviceAccountId, IEnumerable<Project> projects, EventType type, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var project in projects)
{
if (!CanUseEvents(orgAbilities, project.OrganizationId))
{
continue;
}
var e = new EventMessage(_currentContext)
{
OrganizationId = project.OrganizationId,
Type = type,
ProjectId = project.Id,
ServiceAccountId = serviceAccountId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
await _eventWriteService.CreateManyAsync(eventMessages);
}
public async Task LogServiceAccountPeopleEventAsync(Guid userId, UserServiceAccountAccessPolicy policy, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
var orgUser = await _organizationUserRepository.GetByIdAsync((Guid)policy.OrganizationUserId);
if (!CanUseEvents(orgAbilities, orgUser.OrganizationId))
{
return;
}
var (actingUserId, serviceAccountId) = MapIdentityClientType(userId, identityClientType);
if (actingUserId is null && serviceAccountId is null)
{
return;
}
if (policy.OrganizationUserId != null)
{
var e = new EventMessage(_currentContext)
{
OrganizationId = orgUser.OrganizationId,
Type = type,
GrantedServiceAccountId = policy.GrantedServiceAccountId,
ServiceAccountId = serviceAccountId,
UserId = policy.OrganizationUserId,
ActingUserId = actingUserId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
await _eventWriteService.CreateManyAsync(eventMessages);
}
}
public async Task LogServiceAccountGroupEventAsync(Guid userId, GroupServiceAccountAccessPolicy policy, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
if (!CanUseEvents(orgAbilities, policy.Group.OrganizationId))
{
return;
}
var (actingUserId, serviceAccountId) = MapIdentityClientType(userId, identityClientType);
if (actingUserId is null && serviceAccountId is null)
{
return;
}
if (policy.GroupId != null)
{
var e = new EventMessage(_currentContext)
{
OrganizationId = policy.Group.OrganizationId,
Type = type,
GrantedServiceAccountId = policy.GrantedServiceAccountId,
ServiceAccountId = serviceAccountId,
GroupId = policy.GroupId,
ActingUserId = actingUserId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
await _eventWriteService.CreateManyAsync(eventMessages);
}
}
public async Task LogServiceAccountEventAsync(Guid userId, List<ServiceAccount> serviceAccounts, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
var eventMessages = new List<IEvent>();
foreach (var serviceAccount in serviceAccounts)
{
if (!CanUseEvents(orgAbilities, serviceAccount.OrganizationId))
{
continue;
}
var (actingUserId, serviceAccountId) = MapIdentityClientType(userId, identityClientType);
if (actingUserId is null && serviceAccountId is null)
{
continue;
}
if (serviceAccount != null)
{
var e = new EventMessage(_currentContext)
{
OrganizationId = serviceAccount.OrganizationId,
Type = type,
GrantedServiceAccountId = serviceAccount.Id,
ServiceAccountId = serviceAccountId,
ActingUserId = actingUserId,
Date = date.GetValueOrDefault(DateTime.UtcNow)
};
eventMessages.Add(e);
}
}
if (eventMessages.Any())
{
await _eventWriteService.CreateManyAsync(eventMessages);
}
}
private (Guid? actingUserId, Guid? serviceAccountId) MapIdentityClientType(
Guid userId, IdentityClientType identityClientType)
{
if (identityClientType == IdentityClientType.Organization)
{
return (null, null);
}
return identityClientType switch
{
IdentityClientType.User => (userId, null),
IdentityClientType.ServiceAccount => (null, userId),
_ => throw new InvalidOperationException("Unknown identity client type.")
};
}
private async Task<Guid?> GetProviderIdAsync(Guid? orgId)
{
if (_currentContext == null || !orgId.HasValue)
{
return null;
}
return await _currentContext.ProviderIdForOrg(orgId.Value);
}
private Guid? GetInstallationId()
{
if (_currentContext == null)
{
return null;
}
return _currentContext.InstallationId;
}
private bool CanUseEvents(IDictionary<Guid, OrganizationAbility> orgAbilities, Guid orgId)
{
return orgAbilities != null && orgAbilities.TryGetValue(orgId, out var orgAbility) &&
orgAbility.Enabled && orgAbility.UseEvents;
}
private bool CanUseProviderEvents(IDictionary<Guid, ProviderAbility> providerAbilities, Guid providerId)
{
return providerAbilities != null && providerAbilities.TryGetValue(providerId, out var providerAbility) &&
providerAbility.Enabled && providerAbility.UseEvents;
}
}

View File

@@ -1,158 +0,0 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Interfaces;
using Bit.Core.Auth.Identity;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.SecretsManager.Entities;
using Bit.Core.Vault.Entities;
namespace Bit.Core.Services;
public class NoopEventService : IEventService
{
public Task LogCipherEventAsync(Cipher cipher, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogCipherEventsAsync(IEnumerable<Tuple<Cipher, EventType, DateTime?>> events)
{
return Task.FromResult(0);
}
public Task LogCollectionEventAsync(Collection collection, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
Task IEventService.LogCollectionEventsAsync(IEnumerable<(Collection collection, EventType type, DateTime? date)> events)
{
return Task.FromResult(0);
}
public Task LogGroupEventsAsync(
IEnumerable<(Group group, EventType type, EventSystemUser? systemUser, DateTime? date)> events)
{
return Task.FromResult(0);
}
public Task LogPolicyEventAsync(Policy policy, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogGroupEventAsync(Group group, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogGroupEventAsync(Group group, EventType type, EventSystemUser systemUser, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogOrganizationEventAsync(Organization organization, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogProviderUserEventAsync(ProviderUser providerUser, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogProviderUsersEventAsync(IEnumerable<(ProviderUser, EventType, DateTime?)> events)
{
return Task.FromResult(0);
}
public Task LogProviderOrganizationEventAsync(ProviderOrganization providerOrganization, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogProviderOrganizationEventsAsync(IEnumerable<(ProviderOrganization, EventType, DateTime?)> events)
{
return Task.FromResult(0);
}
public Task LogOrganizationDomainEventAsync(OrganizationDomain organizationDomain, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogOrganizationDomainEventAsync(OrganizationDomain organizationDomain, EventType type,
EventSystemUser systemUser,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogOrganizationUserEventAsync<T>(T organizationUser, EventType type, DateTime? date = null) where T : IOrganizationUser
{
return Task.FromResult(0);
}
public Task LogOrganizationUserEventAsync<T>(T organizationUser, EventType type,
EventSystemUser systemUser, DateTime? date = null) where T : IOrganizationUser
{
return Task.FromResult(0);
}
public Task LogOrganizationUserEventsAsync<T>(IEnumerable<(T, EventType, DateTime?)> events) where T : IOrganizationUser
{
return Task.FromResult(0);
}
public Task LogOrganizationUserEventsAsync<T>(IEnumerable<(T, EventType, EventSystemUser, DateTime?)> events) where T : IOrganizationUser
{
return Task.FromResult(0);
}
public Task LogUserEventAsync(Guid userId, EventType type, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogUserSecretsEventAsync(Guid userId, IEnumerable<Secret> secrets, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogServiceAccountSecretsEventAsync(Guid serviceAccountId, IEnumerable<Secret> secrets, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogUserProjectsEventAsync(Guid userId, IEnumerable<Project> projects, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogServiceAccountProjectsEventAsync(Guid serviceAccountId, IEnumerable<Project> projects, EventType type,
DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogServiceAccountPeopleEventAsync(Guid userId, UserServiceAccountAccessPolicy policy, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogServiceAccountGroupEventAsync(Guid userId, GroupServiceAccountAccessPolicy policy, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
return Task.FromResult(0);
}
public Task LogServiceAccountEventAsync(Guid userId, List<ServiceAccount> serviceAccount, EventType type, IdentityClientType identityClientType, DateTime? date = null)
{
return Task.FromResult(0);
}
}

View File

@@ -1,16 +0,0 @@
using Bit.Core.Models.Data;
namespace Bit.Core.Services;
public class NoopEventWriteService : IEventWriteService
{
public Task CreateAsync(IEvent e)
{
return Task.FromResult(0);
}
public Task CreateManyAsync(IEnumerable<IEvent> e)
{
return Task.FromResult(0);
}
}