Exemple #1
0
        public async Task <RecipientResponse> RegenerateRecipientPasswordAsync(RegenerateRecipientPasswordRequest regenRequest)
        {
            var folder = await connection.Folder.GetAsync(regenRequest.FolderIdentifier);

            var recipients = folder.MetaEDiscoveryRecipientListRead();

            var password = ModuleUtility.GeneratePassword(folder, MetadataKeyConstants.E_DISCOVERY_RND_PASSWORD_LENGTH, EDiscoveryUtility.E_DISCOVERY_DEFAULT_PASSWORD_LENGTH, MetadataKeyConstants.E_DISCOVERY_RND_PASSWORD_CHARS);

            var recipient = recipients.Where(rec => rec.Email.ToLower() == regenRequest.RecipientEmail.ToLower()).FirstOrDefault();

            if (recipient != null)
            {
                // Using the special connection here to update their password.
                var userIdentifier = ModuleUtility.GetFolderScopedUserIdentifier(folder.Identifier, regenRequest.RecipientEmail);

                await InitializePrivilegedConnectionAsync();

                await privilegedConnection.User.PasswordPutAsync(userIdentifier, password.Plain);

                await this.auditLogStore.AddEntry(
                    new AuditLogEntry()
                {
                    EntryType  = AuditLogEntryType.eDiscoveryRecipientRegenerated,
                    Message    = $"An eDiscovery has had their password regenerated {recipient.Email}",
                    ModuleType = Modules.ModuleType.eDiscovery
                },
                    folder.Identifier
                    );

                recipient.PasswordHash   = password.Hashed;
                recipient.ExpirationDate = ModuleUtility.GetLinkExpirationDate(folder, MetadataKeyConstants.E_DISCOVERY_EXPIRATION_LENGTH_SECONDS).Value;
                recipient.MagicLink      = ModuleUtility.CreateMagicLink(regenRequest, managerConfiguration.EDiscoveryLandingLocation, managerConfiguration.EDiscoveryLinkEncryptionKey, regenRequest.FolderIdentifier, recipient.ExpirationDate, userIdentifier);

                await connection.ConcurrencyRetryBlock(async() =>
                {
                    folder = await connection.Folder.GetAsync(regenRequest.FolderIdentifier);

                    folder.MetaEDiscoveryRecipientListUpsert(recipient);
                    await connection.Folder.PutAsync(folder);
                });

                // now we also want to send back the magic link that we generated before.
                return(new RecipientResponse()
                {
                    Email = regenRequest.RecipientEmail,
                    FirstName = recipient.FirstName,
                    LastName = recipient.LastName,
                    Password = password.Plain,
                    MagicLink = recipient.MagicLink,
                    ExpirationDate = recipient.ExpirationDate,
                });
            }

            return(new RecipientResponse());
        }
Exemple #2
0
        private async Task EnsureFolderSecurityConfiguration(FolderIdentifier folderIdentifier)
        {
            await privilegedConnection.ConcurrencyRetryBlock(async() =>
            {
                var folder = await privilegedConnection.Folder.GetAsync(folderIdentifier);
                if (!folder.Privilege("read")?.Any(a => a.OverrideKey == "edisc") ?? false)
                {
                    folder.WriteACLs("read", new[] {
                        new ACLModel
                        {
                            OverrideKey         = "edisc",
                            RequiredIdentifiers = new List <string>
                            {
                                "u:system",
                                "x:eDiscovery",
                                $"r:eDiscovery{{{folderIdentifier.FolderKey.Replace(" ", "_")}}}"
                            }
                        }
                    });

                    await privilegedConnection.Folder.PutAsync(folder);
                }
            });
        }
Exemple #3
0
        public async Task <RecipientResponse> AddRecipientAsync(AddOfficerRequest addOfficerRequest, string landingLocation, string passphrase)
        {
            var folder = await connection.Folder.GetAsync(addOfficerRequest.FolderIdentifier);

            DateTime?expirationDate = ModuleUtility.GetLinkExpirationDate(folder, MetadataKeyConstants.LEO_UPLOAD_EXPIRATION_LENGTH_SECONDS);

            var password = ModuleUtility.GeneratePassword(
                folder,
                MetadataKeyConstants.LEO_UPLOAD_RND_PASSWORD_LENGTH,
                LEOUploadUtility.LEO_UPLOAD_DEFAULT_PASSWORD_LENGTH,
                MetadataKeyConstants.LEO_UPLOAD_RND_PASSWORD_CHARS);

            // We're going to generate a user for eDicsovery.  This user will have restricted priveleges.
            var user = await GenerateUser(addOfficerRequest, password.Plain);

            string completeUrl = ModuleUtility.CreateMagicLink(addOfficerRequest, landingLocation, passphrase, folder.Identifier, expirationDate, user.Identifier);

            await connection.ConcurrencyRetryBlock(async() =>
            {
                folder = await connection.Folder.GetAsync(addOfficerRequest.FolderIdentifier);

                folder.MetaLEOUploadOfficerListUpsert(new ExternalUser()
                {
                    Email          = addOfficerRequest.RecipientEmail,
                    FirstName      = addOfficerRequest.FirstName,
                    LastName       = addOfficerRequest.LastName,
                    PasswordHash   = password.Hashed,
                    MagicLink      = completeUrl,
                    ExpirationDate = expirationDate.GetValueOrDefault()
                });

                var childPath = GetOfficerPath(addOfficerRequest.FolderIdentifier, addOfficerRequest.FirstName, addOfficerRequest.LastName);

                var allPaths = folder.Read("_paths", defaultValue: new List <string>());

                allPaths.Add(childPath.FullName);

                folder.Write("_paths", allPaths);

                await connection.Folder.PutAsync(folder);
            });

            await this.auditLogStore.AddEntry(
                new AuditLogEntry()
            {
                EntryType  = AuditLogEntryType.LEOUploadOfficerAdded,
                Message    = $"A LEO officer has been added. {addOfficerRequest.RecipientEmail}",
                ModuleType = Modules.ModuleType.LEOUpload
            },
                folder.Identifier
                );

            // build up the response
            return(new RecipientResponse()
            {
                Email = addOfficerRequest.RecipientEmail,
                ExpirationDate = expirationDate.GetValueOrDefault(),
                MagicLink = completeUrl,
                Password = password.Plain,
                FirstName = addOfficerRequest.FirstName,
                LastName = addOfficerRequest.LastName,
            });
        }
Exemple #4
0
        /// <summary>
        /// In nearly all cases except very specific ones, the connection override should remain null.
        /// </summary>
        /// <param name="auditLogEntry"></param>
        /// <param name="identifier"></param>
        /// <param name="connectionOverride"></param>
        /// <returns></returns>
        public async Task <AuditLogEntry> AddEntry(AuditLogEntry auditLogEntry, FolderIdentifier identifier, APIConnection connectionOverride = null)
        {
            // In some cases we need to be able to pass a special connection in, such is the case for
            // an eDiscovery logged in user.  This connection needs to come in, because we want to use their credentials, and piggy back off their account.
            // The connection in that case as it's passed in through DI won't have a logged in user, and calls to things like 'open folder' will fail.
            if (connectionOverride != null)
            {
                this.connection = connectionOverride;
            }

            var currentUserModel = await connection.User.GetAsync(connection.UserIdentifier);

            // This will save us having to set this everywhere it's created.
            if (!auditLogEntry.Created.HasValue)
            {
                auditLogEntry.Created = DateTime.UtcNow;
            }

            if (String.IsNullOrEmpty(auditLogEntry.UserKey))
            {
                auditLogEntry.UserKey = currentUserModel.Identifier.UserKey;
            }

            if (String.IsNullOrEmpty(auditLogEntry.UserName))
            {
                auditLogEntry.UserName = currentUserModel.EmailAddress;
            }

            // Check to see if there's already an audit log started.  This will give me an empty list, if one
            // doesn't exist, so I'm garunteed this won't result in null.
            var auditLogMetadataEntries = await this.GetAllEntries(identifier);

            var lastEntry = new AuditLogEntry();

            if (auditLogMetadataEntries.Count > 0)
            {
                lastEntry = auditLogMetadataEntries[auditLogMetadataEntries.Count - 1];
            }

            // we're only going to add an audit log entry if there's something different in this entry
            // and the last entry.  The created date will always be different, so we're checking these properties individualy.
            if (lastEntry.Message != auditLogEntry.Message ||
                lastEntry.EntryType != auditLogEntry.EntryType ||
                lastEntry.UserKey != auditLogEntry.UserKey ||
                lastEntry.UserName != auditLogEntry.UserName ||
                lastEntry.ModuleType != auditLogEntry.ModuleType
                )
            {
                auditLogMetadataEntries.Add(auditLogEntry);
                await connection.ConcurrencyRetryBlock(async() =>
                {
                    var folder = await connection.Folder.GetAsync(identifier);

                    folder.Write(AUDIT_LOG_LOCATION, auditLogMetadataEntries);
                    await connection.Folder.PutAsync(folder);
                });

                return(auditLogEntry);
            }

            return(null);
        }