示例#1
0
        /// <summary>
        /// Stopped
        /// </summary>
        public bool Stop()
        {
            this.Stopping?.Invoke(this, EventArgs.Empty);

            // Audit tool should never stop!!!!!
            if (!this.m_safeToStop)
            {
                AuditData securityAlertData = new AuditData(DateTime.Now, ActionType.Execute, OutcomeIndicator.EpicFail, EventIdentifierType.SecurityAlert, AuditUtil.CreateAuditActionCode(EventTypeCodes.UseOfARestrictedFunction));
                AuditUtil.AddDeviceActor(securityAlertData);
                AuditUtil.SendAudit(securityAlertData);
            }

            this.Stopped?.Invoke(this, EventArgs.Empty);
            return(true);
        }
        /// <summary>
        /// Fids the specified audit in the local repository
        /// </summary>
        public IEnumerable <AuditData> Find(Expression <Func <AuditData, bool> > query, int offset, int?count, out int totalResults)
        {
            try
            {
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var builder = new QueryBuilder(this.m_mapper);
                    var sql     = builder.CreateQuery(query).Build();
                    sql = sql.OrderBy <DbAuditData>(o => o.Timestamp, SortOrderType.OrderByDescending);

                    // Total results
                    totalResults = conn.ExecuteScalar <Int32>($"SELECT COUNT(*) FROM ({sql.SQL})", sql.Arguments.ToArray());

                    // Query control
                    if (count.HasValue)
                    {
                        sql.Limit(count.Value);
                    }
                    if (offset > 0)
                    {
                        if (count == 0)
                        {
                            sql.Limit(100).Offset(offset);
                        }
                        else
                        {
                            sql.Offset(offset);
                        }
                    }
                    sql = sql.Build();
                    var itm = conn.Query <DbAuditData.QueryResult>(sql.SQL, sql.Arguments.ToArray());
                    AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.Success, sql.ToString(), itm.Select(o => new Guid(o.Id)).ToArray());
                    return(itm.Select(o => this.ToModelInstance(conn, o)).ToList());
                }
            }
            catch (Exception e)
            {
                AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.EpicFail, query.ToString());
                this.m_tracer.TraceError("Could not query audit {0}: {1}", query, e);
                throw;
            }
        }
        /// <summary>
        /// Prune the audit database
        /// </summary>
        public void Prune()
        {
            var config = ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>();

            try
            {
                this.m_tracer.TraceInfo("Prune audits older than {0}", config?.AuditRetention);
                if (config?.AuditRetention == null)
                {
                    return;                                 // keep audits forever
                }
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    try
                    {
                        conn.BeginTransaction();
                        DateTime cutoff = DateTime.Now.Subtract(config.AuditRetention);
                        Expression <Func <DbAuditData, bool> > epred = o => o.CreationTime < cutoff;
                        conn.Table <DbAuditData>().Delete(epred);

                        // Delete objects
                        conn.Execute($"DELETE FROM {conn.GetMapping<DbAuditObject>().TableName} WHERE NOT({conn.GetMapping<DbAuditObject>().FindColumnWithPropertyName(nameof(DbAuditObject.AuditId)).Name} IN " +
                                     $"(SELECT {conn.GetMapping<DbAuditData>().FindColumnWithPropertyName(nameof(DbAuditData.Id)).Name} FROM {conn.GetMapping<DbAuditData>().TableName})" +
                                     ")");

                        AuditUtil.AuditAuditLogUsed(ActionType.Delete, OutcomeIndicator.Success, epred.ToString());
                        conn.Commit();
                    }
                    catch
                    {
                        conn.Rollback();
                    }
                }
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error pruning audit database: {0}", e);
                throw;
            }
        }
        /// <summary>
        /// Get the specified audit data from the database
        /// </summary>
        public AuditData Get(object id)
        {
            try
            {
                Guid pk = Guid.Empty;
                if (id is Guid)
                {
                    pk = (Guid)id;
                }
                else if (id is String)
                {
                    pk = Guid.Parse(id.ToString());
                }
                else
                {
                    throw new ArgumentException("Parameter must be GUID or parsable as GUID", nameof(id));
                }

                // Fetch
                var conn = this.CreateConnection();
                using (conn.Lock())
                {
                    var builder = new QueryBuilder(this.m_mapper);
                    var sql     = builder.CreateQuery <AuditData>(o => o.CorrelationToken == pk).Limit(1).Build();

                    var res = conn.Query <DbAuditData.QueryResult>(sql.SQL, sql.Arguments.ToArray()).FirstOrDefault();
                    AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.Success, sql.ToString(), pk);

                    return(this.ToModelInstance(conn, res, false));
                }
            }
            catch (Exception e)
            {
                AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.EpicFail, id.ToString());
                this.m_tracer.TraceError("Error retrieving audit {0} : {1}", id, e);
                throw;
            }
        }
示例#5
0
        /// <summary>
        /// Start auditor service
        /// </summary>
        public bool Start()
        {
            this.Starting?.Invoke(this, EventArgs.Empty);

            this.m_safeToStop = false;
            ApplicationContext.Current.Started += (o, e) =>
            {
                try
                {
                    this.m_tracer.TraceInfo("Binding to service events...");

                    ApplicationContext.Current.GetService <IIdentityProviderService>().Authenticated += (so, se) =>
                    {
                        if ((se.Principal?.Identity.Name ?? se.UserName).ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower())
                        {
                            AuditUtil.AuditLogin(se.Principal, se.UserName, so as IIdentityProviderService, se.Success);
                        }
                    };
                    ApplicationContext.Current.GetService <QueueManagerService>().QueueExhausted += (so, se) =>
                    {
                        if (se.ObjectKeys.Count() > 0)
                        {
                            switch (se.Queue)
                            {
                            case "inbound":
                                if (SynchronizationQueue.Inbound.Count() == 0)
                                {
                                    AuditUtil.AuditDataAction <IdentifiedData>(EventTypeCodes.Import, ActionType.Create, AuditableObjectLifecycle.Import, EventIdentifierType.Import, OutcomeIndicator.Success, null);
                                }
                                break;

                            case "outbound":
                                if (SynchronizationQueue.Outbound.Count() == 0)
                                {
                                    AuditUtil.AuditDataAction <IdentifiedData>(EventTypeCodes.Export, ActionType.Execute, AuditableObjectLifecycle.Export, EventIdentifierType.Export, OutcomeIndicator.Success, null);
                                }
                                break;
                            }
                        }
                    };

                    // Scan for IRepositoryServices and bind to their events as well
                    foreach (var svc in ApplicationContext.Current.GetServices().OfType <IAuditEventSource>())
                    {
                        svc.DataCreated += (so, se) =>
                        {
                            if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower())
                            {
                                AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Create, AuditableObjectLifecycle.Creation, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray());
                            }
                        };
                        svc.DataUpdated += (so, se) =>
                        {
                            if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower())
                            {
                                AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Update, AuditableObjectLifecycle.Amendment, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray());
                            }
                        };
                        svc.DataObsoleted += (so, se) =>
                        {
                            if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower())
                            {
                                AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Delete, AuditableObjectLifecycle.LogicalDeletion, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray());
                            }
                        };
                        svc.DataDisclosed += (so, se) =>
                        {
                            if (se.Objects.Count() > 0 && se.Objects.Any(i => i is Patient || i is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower() &&
                                AuthenticationContext.Current.Principal.Identity.Name.ToLower() != "system")
                            {
                                AuditUtil.AuditDataAction(EventTypeCodes.Query, ActionType.Read, AuditableObjectLifecycle.Disclosure, EventIdentifierType.Query, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, se.Query, se.Objects.OfType <IdentifiedData>().ToArray());
                            }
                        };

                        if (svc is ISecurityAuditEventSource)
                        {
                            (svc as ISecurityAuditEventSource).SecurityAttributesChanged += (so, se) => AuditUtil.AuditSecurityAttributeAction(se.Objects, se.Success, se.ChangedProperties);
                        }
                    }

                    AuditUtil.AuditApplicationStartStop(EventTypeCodes.ApplicationStart);
                }
                catch (Exception ex)
                {
                    this.m_tracer.TraceError("Error starting up audit repository service: {0}", ex);
                }
            };
            ApplicationContext.Current.Stopped  += (o, e) => AuditUtil.AuditApplicationStartStop(EventTypeCodes.ApplicationStop);
            ApplicationContext.Current.Stopping += (o, e) => this.m_safeToStop = true;

            AuditInfo sendAudit = new AuditInfo();

            // Send audit
            Action <Object> timerQueue = null;

            timerQueue = o =>
            {
                lock (sendAudit)
                    if (sendAudit.Audit.Count > 0)
                    {
                        SynchronizationQueue.Admin.Enqueue(new AuditInfo()
                        {
                            Audit = new List <AuditData>(sendAudit.Audit)
                        }, Synchronization.Model.DataOperationType.Insert);
                        sendAudit.Audit.Clear();
                    }
                ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(new TimeSpan(0, 0, 30), timerQueue, null);
            };

            // Queue user work item for sending
            ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(new TimeSpan(0, 0, 30), timerQueue, null);

            // Queue pooled item
            ApplicationContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem(o =>
            {
                while (!this.m_safeToStop)
                {
                    try
                    {
                        this.m_resetEvent.WaitOne();
                        while (this.m_auditQueue.Count > 0)
                        {
                            AuditData ad = null;

                            lock (this.m_auditQueue)
                                ad = this.m_auditQueue.Dequeue();

                            try
                            {
                                // First, save the audit locally
                                var ar = ApplicationContext.Current.GetService <IAuditRepositoryService>();
                                if (ar == null)
                                {
                                    throw new InvalidOperationException("!!SECURITY ALERT!! >> Cannot find audit repository");
                                }
                                ad = ar.Insert(ad);

                                lock (sendAudit)
                                    sendAudit.Audit.Add(ad);
                            }
                            catch (Exception e)
                            {
                                this.m_tracer.TraceError("!!SECURITY ALERT!! >> Error sending audit {0}: {1}", ad, e);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceError("!!SECURITY ALERT!! >> Error polling audit task list {0}", e);
                    }
                }
            }, null);
            this.Started?.Invoke(this, EventArgs.Empty);
            return(true);
        }