コード例 #1
0
        /// <summary>
        /// Establish provenance for the specified connection
        /// </summary>
        public static Guid EstablishProvenance(this DataContext me, IPrincipal principal, Guid?externalRef)
        {
            // First, we want to get the identities
            var cprincipal = (principal ?? AuthenticationContext.Current.Principal) as IClaimsPrincipal;
            DbSecurityProvenance retVal = new DbSecurityProvenance()
            {
                Key            = me.ContextId,
                ApplicationKey = Guid.Parse(AuthenticationContext.SystemApplicationSid),
                ExternalSecurityObjectRefKey  = externalRef,
                ExternalSecurityObjectRefType = externalRef != null ?
                                                (me.Count <DbSecurityUser>(o => o.Key == externalRef) > 0 ? "U" : "P") : null
            };

            // Identities
            if (cprincipal != null) // claims principal?
            {
                foreach (var ident in cprincipal.Identities)
                {
                    if (ident is DeviceIdentity)
                    {
                        retVal.DeviceKey = ident.GetKey(me);
                    }
                    else if (ident is Server.Core.Security.ApplicationIdentity)
                    {
                        retVal.ApplicationKey = ident.GetKey(me).Value;
                    }
                    else
                    {
                        retVal.UserKey = ident.GetKey(me);
                    }
                }
                // Session identifier
                var  sidClaim = cprincipal?.FindFirst(SanteDBClaimTypes.SanteDBSessionIdClaim)?.Value;
                Guid sid      = Guid.Empty;
                if (Guid.TryParse(sidClaim, out sid))
                {
                    retVal.SessionKey = sid;
                }
            }
            else if (principal.Identity.Name == AuthenticationContext.SystemPrincipal.Identity.Name)
            {
                retVal.UserKey = Guid.Parse(AuthenticationContext.SystemUserSid);
            }
            else if (principal.Identity.Name == AuthenticationContext.AnonymousPrincipal.Identity.Name)
            {
                retVal.UserKey = Guid.Parse(AuthenticationContext.AnonymousUserSid);
            }

            // Context
            try
            {
                if (retVal.UserKey.ToString() == AuthenticationContext.SystemUserSid ||
                    retVal.UserKey.ToString() == AuthenticationContext.AnonymousUserSid)
                {
                    retVal.Key = me.ContextId = retVal.UserKey.Value;
                }
                else
                {
                    retVal = me.Insert(retVal);
                }
            }
            catch (Exception e)
            {
                s_traceSource.TraceWarning("Error creating context: {0}", e);
                throw new DataPersistenceException($"Error establishing provenance for {principal.Identity.Name}", e);
            }
            return(retVal.Key);
        }
コード例 #2
0
        /// <summary>
        /// Verify the identities are appropriately designed
        /// </summary>
        private void VerifyIdentities(DataContext context, Entity data, Guid?assertedCreator)
        {
            // Validate unique values for IDs
            DbSecurityProvenance provenance = null;
            var issues   = new List <DetectedIssue>();
            var priority = this.m_persistenceService.GetConfiguration().Validation.ValidationLevel;

            foreach (var id in data.Identifiers)
            {
                // Get ID
                var dbAuth = context.FirstOrDefault <DbAssigningAuthority>(o => o.Key == id.AuthorityKey);
                if (dbAuth == null)
                {
                    dbAuth = context.FirstOrDefault <DbAssigningAuthority>(o => o.DomainName == id.Authority.DomainName);
                    if (dbAuth != null)
                    {
                        id.AuthorityKey = dbAuth.Key;
                    }
                }
                if (dbAuth == null)
                {
                    issues.Add(new DetectedIssue(priority, "id.aa.notFound", $"Missing assigning authority with ID {String.Join(",", data.Identifiers.Select(o => o.AuthorityKey))}", DetectedIssueKeys.SafetyConcernIssue));
                    continue;
                }

                // Get this identifier records which is not owned by my record
                var ownedByOthers = context.Query <DbEntityIdentifier>(
                    context.CreateSqlStatement()
                    .SelectFrom(typeof(DbEntityIdentifier))
                    .Where <DbEntityIdentifier>(o => o.Value == id.Value && o.AuthorityKey == id.AuthorityKey && o.ObsoleteVersionSequenceId == null && o.SourceKey != data.Key)
                    .And("NOT EXISTS (SELECT 1 FROM ent_rel_tbl WHERE src_ent_id = ? OR trg_ent_id = ? AND obslt_vrsn_seq_id IS NULL)", data.Key, data.Key)
                    ).ToList();
                var ownedByMe = context.Query <DbEntityIdentifier>(
                    context.CreateSqlStatement()
                    .SelectFrom(typeof(DbEntityIdentifier))
                    .Where <DbEntityIdentifier>(o => o.Value == id.Value && o.AuthorityKey == id.AuthorityKey && o.ObsoleteVersionSequenceId == null)
                    .And("(ent_id = ? OR EXISTS (SELECT 1 FROM ent_rel_tbl WHERE src_ent_id = ? OR trg_ent_id = ? AND obslt_vrsn_seq_id IS NULL))", data.Key, data.Key, data.Key)
                    ).ToList();

                // Verify scope
                var scopes = context.Query <DbAuthorityScope>(o => o.AssigningAuthorityKey == dbAuth.Key);
                if (scopes.Any() && !scopes.Any(s => s.ScopeConceptKey == data.ClassConceptKey) && // This type of identifier is not allowed to be assigned to this type of object
                    !ownedByOthers.Any() &&
                    !ownedByMe.Any())    // Unless it was already associated to another type of object related to me
                {
                    issues.Add(new DetectedIssue(DetectedIssuePriorityType.Error, "id.target", $"Identifier of type {dbAuth.DomainName} cannot be assigned to object of type {data.ClassConceptKey}", DetectedIssueKeys.BusinessRuleViolationIssue));
                }

                // If the identity domain is unique, and we've been asked to raid identifier uq issues
                if (dbAuth.IsUnique && this.m_persistenceService.GetConfiguration().Validation.IdentifierUniqueness&&
                    ownedByOthers.Any())
                {
                    issues.Add(new DetectedIssue(priority, $"id.uniqueness", $"Identifier {id.Value} in domain {dbAuth.DomainName} violates unique constraint", DetectedIssueKeys.FormalConstraintIssue));
                }
                if (dbAuth.AssigningApplicationKey.HasValue) // Must have permission
                {
                    if (provenance == null)
                    {
                        provenance = context.FirstOrDefault <DbSecurityProvenance>(o => o.Key == data.CreatedByKey);
                    }


                    if (provenance.ApplicationKey != dbAuth.AssigningApplicationKey && // Established prov key
                        assertedCreator != dbAuth.AssigningApplicationKey &&  // original prov key
                        !ownedByMe.Any() &&
                        !ownedByOthers.Any())    // and has not already been assigned to me or anyone else (it is a new , unknown identifier)
                    {
                        issues.Add(new DetectedIssue(DetectedIssuePriorityType.Error, $"id.authority", $"Application {provenance.ApplicationKey} does not have permission to assign {dbAuth.DomainName}", DetectedIssueKeys.SecurityIssue));
                    }
                }
                if (!String.IsNullOrEmpty(dbAuth.ValidationRegex) && this.m_persistenceService.GetConfiguration().Validation.IdentifierFormat) // must be valid
                {
                    var nonMatch = !new Regex(dbAuth.ValidationRegex).IsMatch(id.Value);
                    if (nonMatch)
                    {
                        issues.Add(new DetectedIssue(priority, $"id.format", $"Identifier {id.Value} in domain {dbAuth.DomainName} failed format validation", DetectedIssueKeys.FormalConstraintIssue));
                    }
                }
            }

            // Validate issues
            if (issues.Any(o => o.Priority == DetectedIssuePriorityType.Error))
            {
                throw new DetectedIssueException(issues);
            }
            else if (issues.Count > 0)
            {
                var extension = data.Extensions.FirstOrDefault(o => o.ExtensionTypeKey == ExtensionTypeKeys.DataQualityExtension);
                if (extension == null)
                {
                    data.Extensions.Add(new EntityExtension(ExtensionTypeKeys.DataQualityExtension, typeof(DictionaryExtensionHandler), issues));
                }
                else
                {
                    var existingValues = extension.GetValue <List <DetectedIssue> >();
                    existingValues.AddRange(issues);
                    extension.ExtensionValue = existingValues;
                }
            }
        }