Пример #1
0
 private void SetupInitialValues(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule connectorRule)
 {
     Tracer.TraceInformation("enter-setupinitialvalues");
     try
     {
         if (connectorRule.Helpers != null)
         {
             Tracer.TraceInformation("generating-helper-values");
             foreach (HelperValue helper in connectorRule.Helpers)
             {
                 helper.Generate();
             }
         }
         foreach (AttributeFlowBase attributeBase in connectorRule.InitialFlows)
         {
             attributeBase.Generate(ma, csentry, mventry, connectorRule);
         }
     }
     catch (Exception ex)
     {
         Tracer.TraceError("error {0}", ex.GetBaseException());
         throw;
     }
     finally
     {
         Tracer.TraceInformation("exit-setupinitialvalues");
     }
 }
Пример #2
0
        public override void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
        {
            Tracer.TraceInformation("enter-attributeflowguid");
            base.Generate(ma, csentry, mventry, rule);
            try
            {
                Guid newGuid = Guid.NewGuid();
                Tracer.TraceInformation("new-guid-'{0}'-to-'{1}'", newGuid.ToString(), this.Target);

                if (this.Target.Equals("[DN]", StringComparison.OrdinalIgnoreCase))
                {
                    csentry.DN = csentry.MA.CreateDN(newGuid.ToString());
                }
                else
                {
                    csentry[this.Target].Value = newGuid.ToString();
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-attributeflowguid");
            }
        }
Пример #3
0
        private void CreateConnector(ConnectedMA ma, MVEntry mventry, Rule rule)
        {
            Tracer.TraceInformation("enter-createconnector");
            try
            {
                Tracer.TraceInformation("create-connector: MV: '{0}', MA: '{1}'", mventry.ObjectID, ma.Name);
                IList <string> additionalObjectClasses = this.GetAdditionalObjectClasses(mventry, rule);
                CSEntry        csentry;

                if (additionalObjectClasses.Count > 0)
                {
                    csentry = ma.Connectors.StartNewConnector(rule.TargetObject, additionalObjectClasses.ToArray());
                }
                else
                {
                    csentry = ma.Connectors.StartNewConnector(rule.TargetObject);
                }

                this.SetupInitialValues(ma, csentry, mventry, rule);
                csentry.CommitNewConnector();
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-createconnector");
            }
        }
Пример #4
0
        public override bool Met(MVEntry mventry, CSEntry csentry)
        {
            ConnectedMA MA = mventry.ConnectedMAs[this.ManagementAgentName];

            if (MA.Connectors.Count.Equals(0))
            {
                Tracer.TraceInformation("Condition failed (Reason: Not connected to {0}) {1}", this.ManagementAgentName, this.Description);
                return(false);
            }
            return(true);
        }
        public override void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
        {
            Tracer.TraceInformation("enter-attributeflowmultivaluedconstant");

            if (Target.Equals("[DN]", StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException("Cannot use a multivalued constant flow on the DN of an object");
            }

            if (this.Constants == null)
            {
                throw new ArgumentException("The <Constants> element must be present with one or more values when using a multivalued constant attribute flow rule");
            }

            base.Generate(ma, csentry, mventry, rule);

            try
            {
                foreach (string constant in this.Constants)
                {
                    string escapedCN     = null;
                    string replacedValue = null;
                    replacedValue = constant.ReplaceWithHelperValuesOrBlank(rule.Helpers);

                    if (string.IsNullOrEmpty(this.EscapedCN))
                    {
                        Tracer.TraceInformation("no-CN-to-escape");
                        replacedValue = replacedValue.ReplaceWithMVValueOrBlank(mventry);
                    }
                    else
                    {
                        escapedCN = this.EscapedCN.ReplaceWithHelperValuesOrBlank(rule.Helpers);
                        escapedCN = ma.EscapeDNComponent(this.EscapedCN.ReplaceWithMVValueOrBlank(mventry, "")).ToString();
                        Tracer.TraceInformation("escaped-cn '{0}'", escapedCN);
                        replacedValue = replacedValue.ReplaceWithMVValueOrBlank(mventry, escapedCN);
                    }
                    Tracer.TraceInformation("flow-mv-constant-'{0}'-to-'{1}'", replacedValue, this.Target);

                    csentry[(this.Target)].Values.Add(replacedValue);
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-attributeflowmutlivaluedconstant");
            }
        }
Пример #6
0
        private void ConditionalRenameConnector(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule connectorRule)
        {
            Tracer.TraceInformation("enter-conditionalrenameconnector");
            try
            {
                if (connectorRule.ConditionalRename == null)
                {
                    return;
                }

                string escapedCN     = null;
                string replacedValue = null;
                if (string.IsNullOrEmpty(connectorRule.ConditionalRename.EscapedCN))
                {
                    Tracer.TraceInformation("no-cn-to-escape");
                    replacedValue = connectorRule.ConditionalRename.NewDNValue.ReplaceWithMVValueOrBlank(mventry);
                }
                else
                {
                    escapedCN = ma.EscapeDNComponent(connectorRule.ConditionalRename.EscapedCN.ReplaceWithMVValueOrBlank(mventry, "")).ToString();
                    Tracer.TraceInformation("escaped-cn {0}", escapedCN);
                    replacedValue = connectorRule.ConditionalRename.NewDNValue.ReplaceWithMVValueOrBlank(mventry, escapedCN);
                }

                ReferenceValue newdn = ma.CreateDN(replacedValue);
                ReferenceValue olddn = ma.CreateDN(csentry.DN.ToString());
                Tracer.TraceInformation("old-dn '{0}'", olddn.ToString());
                Tracer.TraceInformation("new-dn '{0}'", newdn.ToString());

                if (this.AreDNsEqual(olddn, newdn, ma, connectorRule.ConditionalRename.StrictDNCompare))
                {
                    Tracer.TraceInformation("no-renaming-necessary");
                }
                else
                {
                    Tracer.TraceInformation("dn-rename-required");
                    csentry.DN = newdn;
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-conditionalrenameconnector");
            }
        }
Пример #7
0
 private void DeprovisionConnector(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule connectorRule)
 {
     Tracer.TraceInformation("enter-deprovisionconnector");
     try
     {
         Tracer.TraceInformation("deprovision-connector: DN: '{0}', MA: '{1}'", csentry.DN, csentry.MA.Name);
         csentry.Deprovision();
     }
     catch (Exception ex)
     {
         Tracer.TraceError("error {0}", ex.GetBaseException());
         throw;
     }
     finally
     {
         Tracer.TraceInformation("exit-deprovisionconnector");
     }
 }
        private void ProvisionPerson(ConnectedMA agent, MVEntry mventry)
        {
            CSEntry        csentry;
            ReferenceValue dn;
            string         accountName;
            string         basePath;
            string         companyName;

            if (agent == null)
            {
                throw new ArgumentNullException(nameof(agent));
            }
            if (mventry == null)
            {
                throw new ArgumentNullException(nameof(mventry));
            }

            try
            {
                accountName = mventry["userPrincipalName"].Value.Split('@')[0];
                basePath    = $"{_users},OU={mventry["company"].Value},{_root}";
                companyName = mventry["company"].Value.Replace(" ", string.Empty);

                dn = agent.CreateDN(
                    $"CN={mventry["displayName"].Value},{basePath}");
                csentry    = agent.Connectors.StartNewConnector("user");
                csentry.DN = dn;
                csentry["company"].Value                   = mventry["company"].Value;
                csentry["displayName"].Value               = mventry["displayName"].Value;
                csentry["givenName"].Value                 = mventry["firstName"].Value;
                csentry["sAMAccountName"].Value            = $"{accountName}_{companyName}";
                csentry["sn"].Value                        = mventry["lastName"].Value;
                csentry["unicodePwd"].Value                = _password;
                csentry["userAccountControl"].IntegerValue = ADS_UF_ACCOUNTDISABLE;
                csentry["userPrincipalName"].Value         = mventry["userPrincipalName"].Value;
                csentry.CommitNewConnector();
            }
            finally
            {
                csentry = null;
                dn      = null;
            }
        }
Пример #9
0
        public override void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
        {
            Tracer.TraceInformation("enter-attributeflowconstant");
            base.Generate(ma, csentry, mventry, rule);
            try
            {
                string escapedCN     = null;
                string replacedValue = null;
                replacedValue = this.Constant.ReplaceWithHelperValuesOrBlank(rule.Helpers);

                if (string.IsNullOrEmpty(this.EscapedCN))
                {
                    Tracer.TraceInformation("no-CN-to-escape");
                    replacedValue = replacedValue.ReplaceWithMVValueOrBlank(mventry);
                }
                else
                {
                    escapedCN = this.EscapedCN.ReplaceWithHelperValuesOrBlank(rule.Helpers);
                    escapedCN = ma.EscapeDNComponent(this.EscapedCN.ReplaceWithMVValueOrBlank(mventry, "")).ToString();
                    Tracer.TraceInformation("escaped-cn '{0}'", escapedCN);
                    replacedValue = replacedValue.ReplaceWithMVValueOrBlank(mventry, escapedCN);
                }
                Tracer.TraceInformation("flow-constant-'{0}'-to-'{1}'", replacedValue, this.Target);
                if (this.Target.Equals("[DN]", StringComparison.OrdinalIgnoreCase))
                {
                    csentry.DN = csentry.MA.CreateDN(replacedValue);
                }
                else
                {
                    csentry[(this.Target)].Value = replacedValue;
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-attributeflowconstant");
            }
        }
        private void ProvisionCustomer(ConnectedMA agent, MVEntry mventry)
        {
            CSEntry        csentry;
            ReferenceValue dn;

            if (agent == null)
            {
                throw new ArgumentNullException(nameof(agent));
            }
            if (mventry == null)
            {
                throw new ArgumentNullException(nameof(mventry));
            }

            try
            {
                /* Define the appropriate provisioning logic here. */
            }
            finally
            {
                csentry = null;
                dn      = null;
            }
        }
        void IMVSynchronization.Provision(MVEntry mventry)
        {
            //get our provisioning ma from the db
            string provisioningMAName = FIMConfiguration.GetProvisioningMA()["ma_name"].ToString();

            XmlDocument xmldoc     = FIMConfiguration.GetConfigXML(provisioningMAName, "private_configuration_xml");
            XmlNodeList attributes = xmldoc.SelectNodes("//MAConfig/parameter-values/parameter");

            //loop through each MA/object type selected
            foreach (XmlNode attrib in attributes)
            {
                string param      = attrib.Attributes["name"].Value;
                string maName     = param.Substring(0, param.LastIndexOf(" - "));
                string objectType = param.Substring(param.LastIndexOf(" - ") + 3);

                //if enabled, provision it
                if (attrib.InnerText.Equals("1"))
                {
                    //our ma has been enabled for provisioning, create a new csentry and add initial flows
                    ConnectedMA ma = mventry.ConnectedMAs[maName];

                    if (ma.Connectors.Count == 0)
                    {
                        CSEntry csentry = ma.Connectors.StartNewConnector(objectType);

                        //go and get the real anchor info, our provisioning ma
                        //uses a generic anchor to ensure tha flows can be
                        //defined for the actual anchor
                        XmlDocument maSchemaConfig = FIMConfiguration.GetConfigXML(maName, "dn_construction_xml");
                        XmlNode     maSchemaRoot   = maSchemaConfig.FirstChild;

                        //get dn for the object
                        List <string> anchors = new List <string>();
                        if (maSchemaRoot.FirstChild.Name.Equals("attribute", StringComparison.InvariantCultureIgnoreCase))
                        {
                            XmlNodeList anchorList = maSchemaConfig.SelectNodes("//dn-construction/attribute");

                            foreach (XmlNode anchor in anchorList)
                            {
                                anchors.Add(anchor.InnerText);
                            }
                        }
                        else
                        {
                            XmlNodeList anchorList = maSchemaConfig.SelectNodes("//dn-construction/dn[@object-type='" + objectType + "']/attribute");

                            foreach (XmlNode anchor in anchorList)
                            {
                                anchors.Add(anchor.InnerText);
                            }
                        }

                        //our export schema defines the initial attributes to flow
                        XmlDocument xmlFlows = FIMConfiguration.GetConfigXML(provisioningMAName, "export_attribute_flow_xml");
                        XmlNodeList flows    = xmlFlows.SelectNodes("//export-attribute-flow/export-flow-set[@cd-object-type='" + maName + "']/export-flow");

                        foreach (XmlNode flow in flows)
                        {
                            //get the mapping for each flow defined and provision an initial flow
                            string csAttribName = flow.Attributes["cd-attribute"].Value;
                            csAttribName = csAttribName.Substring(csAttribName.LastIndexOf(" - ") + 3);

                            XmlNode         mappingNode = flow.FirstChild;
                            string          mappingType = mappingNode.Name;
                            string          flowValue   = null;
                            ValueCollection flowValues  = null;

                            switch (mappingType)
                            {
                            case "direct-mapping":

                                string mvAttribName = mappingNode.FirstChild.InnerText;

                                if (mventry[mvAttribName].IsPresent)
                                {
                                    if (mventry[mvAttribName].IsMultivalued)
                                    {
                                        flowValues = mventry[mvAttribName].Values;
                                    }
                                    else
                                    {
                                        //TODO: convert this to its proper type if necessary (i.e. int, boolean, etc)
                                        flowValue = mventry[mvAttribName].Value;
                                    }
                                }
                                break;

                            case "constant-mapping":
                                flowValue = mappingNode.FirstChild.InnerText;
                                break;

                            case "scripted-mapping":
                                break;

                            default:
                                throw new Exception("Unexpected mapping type encountered. Only Direct, Constant and Advanced/Scripted flows are allowed. Check flow rules and try again.");
                            }

                            if (flowValue != null || flowValues != null)
                            {
                                //calc dn if necessary
                                if (csAttribName.Equals("dn", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    //are we safe to assume that if we are calculating dn, we must
                                    //be using flowValue and not flowValues?
                                    string         rdn = flowValue.ToString();
                                    ReferenceValue dn  = ma.EscapeDNComponent(rdn);
                                    csentry.DN = dn;
                                }
                                else
                                {
                                    try
                                    {
                                        if (flowValue != null)
                                        {
                                            csentry[csAttribName].Values.Add(flowValue);
                                        }
                                        else if (flowValues != null)
                                        {
                                            csentry[csAttribName].Values.Add(flowValues);
                                        }
                                    }
                                    catch (InvalidOperationException ex)
                                    {
                                        if (!ex.Message.Equals("attribute " + csAttribName + " is read-only", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            throw;
                                        }
                                        else
                                        {
                                            //our anchor attribute is read only, set a temporary dn
                                            if (anchors.Contains(csAttribName))
                                            {
                                                ReferenceValue dn = ma.EscapeDNComponent(Guid.NewGuid().ToString());
                                                csentry.DN = dn;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        //do we want to throw an error now if any writeable anchor attributes have not been set??
                        //otherwise they will get one on export, we will leave it that way for now

                        csentry.CommitNewConnector();
                    }
                }
            }
        }
Пример #12
0
        public override void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
        {
            Tracer.TraceInformation("enter-attributeflowattribute");

            bool          sourceIsMVObjectID = this.Source.Equals("[mvobjectid]", StringComparison.OrdinalIgnoreCase);
            bool          targetIsDN         = this.Target.Equals("[dn]", StringComparison.OrdinalIgnoreCase);
            AttributeType sourceType;
            AttributeType targetType;

            if (!sourceIsMVObjectID)
            {
                sourceType = mventry[this.Source].DataType;
            }
            else
            {
                sourceType = AttributeType.String;
            }

            if (!targetIsDN)
            {
                targetType = csentry[this.Target].DataType;
            }
            else
            {
                targetType = AttributeType.String;
            }

            if (sourceIsMVObjectID)
            {
                Tracer.TraceInformation("flow-source-value: '{0}'", mventry.ObjectID.ToString());
                this.FlowMVObjectID(csentry, mventry, targetIsDN, targetType);
                return;
            }
            else
            {
                Tracer.TraceInformation("flow-source-value: '{0}'", mventry[this.Source].Value);
            }

            if (!mventry[this.Source].IsPresent)
            {
                return;
            }

            try
            {
                switch (sourceType)
                {
                case AttributeType.String:
                    this.FlowStringAttribute(csentry, mventry, targetIsDN, targetType);
                    break;

                case AttributeType.Integer:
                    this.FlowIntegerAttribute(csentry, mventry, targetIsDN, targetType);
                    break;

                case AttributeType.Reference:
                    break;

                case AttributeType.Binary:
                    this.FlowBinaryAttribute(csentry, mventry, targetIsDN, targetType);
                    break;

                case AttributeType.Boolean:
                    this.FlowBooleanAttribute(csentry, mventry, targetIsDN, targetType);
                    break;

                default:
                    break;
                }

                if (targetIsDN)
                {
                    Tracer.TraceInformation("target-value: '{0}'", csentry.DN);
                }
                else
                {
                    Tracer.TraceInformation("target-value: '{0}'", csentry[this.Target].Value);
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-attributeflowattribute");
            }
        }
Пример #13
0
        void IMVSynchronization.Provision(MVEntry mventry)
        {
            switch (mventry.ObjectType.ToLower())
            {
                //Person - MV Object type to scope provision of contoso users to the GALSync domain, as contact objects, under the "ExternalContacts" OU
                #region case "person":
                case "person":
                    {

                        bool bContactsConnected = false; // reset our boolean 
                        bool bProv = false;
                        if (mventry["mail"].IsPresent) bProv = true;
                        maContacts = mventry.ConnectedMAs["GALSync"]; //Declares MA to Provisions

                        int iNumConnectorsContacts = maContacts.Connectors.Count; // count our connectors to this MA 

                        if (bProv)
                        {
                            if (iNumConnectorsContacts > 0) bContactsConnected = true;
                            RDN = "CN=" + mventry["cn"].Value + ",OU=ExternalContacts" + ",DC=GALSync,DC=com";
                            targetDN = maContacts.CreateDN(RDN); //Created the CS DN
                            if (!(bContactsConnected)) //If not found while iNumConnectorsContacts
                            {
                                CSEntry = maContacts.Connectors.StartNewConnector("contact"); //Starts a new connector
                                CSEntry.DN = targetDN; //Sets the CS DN from targetDN
                                CSEntry["targetAddress"].Value = mventry["mail"].Value; //flows mail attribute MV > CS
                                CSEntry.CommitNewConnector(); //commits the connector to cs db
                            }
                        }
                        break;
                    }
                #endregion case "person"

                //GALSyncPerson - MV Obkect type to scope provision of external contacts from the GALSync.com domain to AD in Contoso under the "ExternalContacts" OU
                #region case "GalSyncPerson":
                case galsyncperson":
                    {

                        bool bContactsConnected = false; // reset our boolean 
                        bool bProv = false;
                        if (mventry["mail"].IsPresent) bProv = true;
                        maContacts = mventry.ConnectedMAs["AD MA"]; //Declares MA to Provisions

                        int iNumConnectorsContacts = maContacts.Connectors.Count; // count our connectors to this MA 

                        if (bProv)
                        {
                            if (iNumConnectorsContacts > 0) bContactsConnected = true;
                            RDN = "CN=" + mventry["cn"].Value + ",OU=ExternalContacts" + ",DC=Contoso,DC=com";
                            targetDN = maContacts.CreateDN(RDN); //Created the CS DN
                            if (!(bContactsConnected)) //If not found while iNumConnectorsContacts
                            {
                                CSEntry = maContacts.Connectors.StartNewConnector("contact"); //Starts a new connector
                                CSEntry.DN = targetDN; //Sets the CS DN from targetDN
                                CSEntry["targetAddress"].Value = mventry["mail"].Value; //flows mail attribute MV > CS
                                CSEntry.CommitNewConnector(); //commits the connector to cs db
                            }
                        }
                        break;
                    }
                    #endregion case "GalSyncPerson"
            }
        }
Пример #14
0
 public override void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
 {
     Tracer.TraceInformation("enter-attributeflowconcatenate");
     base.Generate(ma, csentry, mventry, rule);
     try
     {
         string concatValue = null;
         foreach (SourceExpressionBase sourceExpression in this.SourceExpressions)
         {
             if (sourceExpression.GetType() == typeof(SourceExpressionConstant))
             {
                 SourceExpressionConstant sourceExpr = (SourceExpressionConstant)sourceExpression;
                 string replacedValue = sourceExpr.Source.ReplaceWithMVValueOrBlank(mventry);
                 Tracer.TraceInformation("adding-constant-'{0}'", replacedValue);
                 concatValue = concatValue + replacedValue;
                 continue;
             }
             if (sourceExpression.GetType() == typeof(SourceExpressionRegexReplace))
             {
                 SourceExpressionRegexReplace sourceExpr = (SourceExpressionRegexReplace)sourceExpression;
                 Tracer.TraceInformation("adding-regex-replacement-'{0}'", sourceExpr.Source);
                 if (mventry[sourceExpr.Source].IsPresent)
                 {
                     concatValue = concatValue + Regex.Replace(mventry[sourceExpr.Source].Value, sourceExpr.Pattern, sourceExpr.Replacement);
                 }
                 else
                 {
                     Tracer.TraceError("attribute-'{0}'-is-not-present-in-metaverse", sourceExpr.Source);
                 }
                 continue;
             }
             if (sourceExpression.GetType() == typeof(SourceExpressionAttribute))
             {
                 SourceExpressionAttribute attr = (SourceExpressionAttribute)sourceExpression;
                 if (mventry[attr.Source].IsPresent)
                 {
                     Tracer.TraceInformation("adding-value-from-MV::'{0}'-to-'{1}'", attr.Source, mventry[attr.Source].Value);
                     concatValue = concatValue + mventry[attr.Source].Value.ToString();
                 }
                 else
                 {
                     Tracer.TraceError("attribute-'{0}'-is-not-present-in-metaverse", attr.Source);
                 }
                 continue;
             }
         }
         Tracer.TraceInformation("flow-concatenated-attribute-value-'{0}'-to-'{1}'", concatValue, this.Target);
         if (this.Target.Equals("[DN]", StringComparison.OrdinalIgnoreCase))
         {
             csentry.DN = csentry.MA.CreateDN(concatValue);
         }
         else
         {
             csentry[(this.Target)].Value = concatValue;
         }
     }
     catch (Exception ex)
     {
         Tracer.TraceError("error {0}", ex.GetBaseException());
         throw;
     }
     finally
     {
         Tracer.TraceInformation("exit-attributeflowconcatenate");
     }
 }
Пример #15
0
        public void Provision(MVEntry mventry)
        {
            int         i = 0;
            CSEntry     MasterConnector = null;
            ConnectedMA MA = default(ConnectedMA);


            //LoggingCs.Log("Entering provisioning for " + mventry.ToString());

            foreach (ConnectedMA ConnMA in mventry.ConnectedMAs)
            {
                //CSEntry csentry = default(CSEntry);
                foreach (CSEntry cseentry in ConnMA.Connectors)
                {
                    if (cseentry.ConnectionRule == RuleType.Projection)
                    {
                        MasterConnector = cseentry;
                    }
                }
            }

            //
            // For every MA, try to add a csentry, if there is not already one
            //

            for (i = 0; i <= galMAs.Length - 1; i++)
            {
                MA = mventry.ConnectedMAs[galMAs[i].MAName];
                if (0 == MA.Connectors.Count)
                {
                    //
                    // If there were no connectors, then we are going to add one

                    AddOrRenameConnector(ref MA, ref galMAs[i], mventry);
                }
                else if (1 == MA.Connectors.Count)
                {
                    //
                    // If there is one connector,
                    // - if it is the master object connector then it is ok.
                    // - if it is a replica object, then check for rename.
                    // - if it is a join object outside the Synchronization
                    //   OU, then it is a problem, log it
                    //
                    CSEntry csentry = MA.Connectors.ByIndex[0];
                    if (IsInSynchronizationOU(csentry))
                    {
                        AddOrRenameConnector(ref MA, ref galMAs[i], mventry, csentry);
                    }
                    else
                    {
                        if ((!object.ReferenceEquals(csentry, MasterConnector)))
                        {
                            //
                            // This object has joined.
                            //
                            string LogString = "A contact for this object " + MasterConnector.ToString() + " called contact " + csentry.ToString() + " already exists in forest represented by MA " + MA.Name + ". If you would like to preserve this " + "contact and have us manage it, please " + "move the contact into Synchronization OU. " + "If you would like us to create " + "a new contact and manage it, " + "please delete this one.";

                            //LoggingCs.Log(LogString);
                        }
                    }
                }
                else
                {
                    //
                    // We have more than one connectors undert the same MA,
                    // print an error message.
                    //
                    CSEntry csentry              = default(CSEntry);
                    int     index                = 0;
                    int     countCsRemaining     = 0;
                    bool    contactOutsideSyncOU = false;

                    string LogString = "Multiple or outside-synchronizaiton-OU " + "connector(s) for the MV object " + MasterConnector.ToString() + "exist, they are: ";


                    for (index = MA.Connectors.Count - 1; index >= 0; index += -1)
                    {
                        csentry = MA.Connectors.ByIndex[index];

                        if (csentry.ConnectionRule == RuleType.Provisioning)
                        {
                            //LoggingCs.Log("Disconnecting provisioned " + csentry.ToString() );
                            csentry.Deprovision();
                        }
                        else
                        {
                            countCsRemaining = countCsRemaining + 1;
                            LogString        = LogString + csentry.ToString() + " lives in forest connected by " + MA.Name + " ";
                            if (!IsInSynchronizationOU(csentry) && csentry.ObjectType == CONTACT)
                            {
                                contactOutsideSyncOU = true;
                            }
                        }
                    }

                    //
                    // If we end up with more than one connector, or
                    // any contact outside synchronization OU,
                    // we want to log a warning message
                    //
                    if ((countCsRemaining > 1) || (true == contactOutsideSyncOU))
                    {
                        LogString = LogString + ". Please refer to documentation " + "to resolve the conflict.";
                        //LoggingCs.Log(LogString);
                    }
                }
            }
        }
Пример #16
0
        void ProvisionUPSA(MVEntry mventry, string MA_name)
        {
            var attr_map = new Dictionary <string, string>()
            {
                { "accountName", "AccountName" },
                { "department", "Department" },
                { "displayName", "UserName" },
                { "mail", "WorkEmail" },
                { "objectSid", "SID" },
                { "lastName", "LastName" },
                { "firstName", "FirstName" },
                { "telephoneNumber", "WorkPhone" },
            };

            ConnectedMA ManagementAgent = mventry.ConnectedMAs[MA_name];
            int         Connectors      = ManagementAgent.Connectors.Count;

            if (0 == Connectors && mventry.ObjectType.Equals("person", StringComparison.OrdinalIgnoreCase))
            {
                if (mventry["accountName"].IsPresent)
                {
                    string  anchor  = mventry["accountName"].Value;
                    CSEntry csentry = ManagementAgent.Connectors.StartNewConnector("user");

                    AttributeNameEnumerator iter = mventry.GetEnumerator();
                    while (iter.MoveNext())
                    {
                        string CS_AttrName;
                        if (attr_map.TryGetValue(iter.Current, out CS_AttrName))
                        {
                            csentry[CS_AttrName].Value = mventry[iter.Current].Value;
                        }
                    }
                    csentry["Anchor"].Value = anchor;
                    csentry.CommitNewConnector();
                }
            }
            if (mventry.ObjectType.ToLower() == "group" && 0 == Connectors)
            {
                try
                {
                    if (mventry["accountName"].IsPresent)
                    {
                        string  anchor  = mventry["accountName"].Value;
                        CSEntry csentry = ManagementAgent.Connectors.StartNewConnector("group");
                        csentry["Anchor"].Value = anchor;
                        csentry.CommitNewConnector();
                    }
                }
                catch (ObjectAlreadyExistsException)
                {
                    // Suppress the exception when an object exists with same distinguished name in the connector space.
                    // The object should join on the next inbound synchronization run
                }
            }
            if (mventry.ObjectType.ToLower() == "contact" && 0 == Connectors)
            {
                try
                {
                    if (mventry["sAMAccountName"].IsPresent)
                    {
                        string  anchor  = mventry["sAMAccountName"].Value;
                        CSEntry csentry = ManagementAgent.Connectors.StartNewConnector("contact");
                        csentry["Anchor"].Value = anchor;
                        csentry.CommitNewConnector();
                    }
                }
                catch (ObjectAlreadyExistsException)
                {
                    // Suppress the exception when an object exists with same distinguished name in the connector space.
                    // The object should join on the next inbound synchronization run
                }
            }
        }
Пример #17
0
 public virtual void Generate(ConnectedMA ma, CSEntry csentry, MVEntry mventry, Rule rule)
 {
     //intentionally left blank
 }
Пример #18
0
        private void AddOrRenameConnector(ref ConnectedMA MA, ref GALMA MAConfig, MVEntry mventry, CSEntry csentry = null)
        {
            //
            // All objects are provisioned as contacts
            //
            string cn                = null;
            int    numberToAppend    = 1;
            bool   successful        = false;
            bool   extendedNameTried = false;
            string extendedName      = null;
            string adminGroup        = null;
            bool   provisioningAdd   = false;
            int    cnLengthMax       = 0;
            string validatedName     = null;

            //
            // Add or Rename if only SynchronizationOU is defined
            //
            if ((MAConfig.SynchronizationOU == null) || MAConfig.SynchronizationOU.Equals(""))
            {
                return;
            }

            if (!mventry[COMMON_NAME].IsPresent || !mventry[MAIL_NICK_NAME].IsPresent || !mventry[TARGET_ADDRESS].IsPresent)
            {
                LogAndThrowUnexpectedDataException("Provisioning without cn, mailNickName or targetAddress");
            }

            if (null == csentry)
            {
                provisioningAdd = true;
            }

            cn = mventry[COMMON_NAME].Value.ToString();

            //
            // Active Directory does not distinguish CNs that differ only in use of diacritical marks (accents) etc.
            // whereas the sync service does. So force uniqueness by appending mailnickname to all CNs with extended
            // chars if doing so does not exceed CN max length.
            //
            IEnumerator cnEnum = cn.GetEnumerator();

            while (cnEnum.MoveNext())
            {
                if (Strings.AscW(cnEnum.Current.ToString()) > 127 && cn.Length + mventry[MAIL_NICK_NAME].Value.ToString().Length + 2 + RDN_TYPE.Length < AD_RDN_MAX_SIZE)
                {
                    cn = cn + "(" + mventry[MAIL_NICK_NAME].Value.ToString() + ")";
                    break;                     // TODO: might not be correct. Was : Exit While
                }
            }

            do
            {
                try {
                    //
                    // Create a DN for the new object, need UPPER case "CN=..."
                    //
                    string         rdn = RDN_TYPE + cn;
                    ReferenceValue dn  = MA.EscapeDNComponent(rdn).Concat(MAConfig.SynchronizationOU);

                    if (rdn.Length > AD_RDN_MAX_SIZE + RDN_TYPE.Length)
                    {
                        LogAndThrowUnexpectedDataException("RDN too long: " + rdn);
                    }

                    if (csentry == null)
                    {
                        //
                        // Try to add the object
                        //
                        //LoggingCs.Log("Adding " + dn.ToString());

                        csentry = ExchangeUtils.CreateMailEnabledContact(MA, dn, mventry[MAIL_NICK_NAME].Value.ToString(), mventry[TARGET_ADDRESS].Value.ToString());

                        adminGroup = GetAdminGroup(csentry);
                        if ((adminGroup != null))
                        {
                            //
                            // LegacyExhangeDN = adminGroup/cn=mailnickname-guid
                            //
                            validatedName = ValidateLegacyExhangeDN(mventry[MAIL_NICK_NAME].Value.ToCharArray());

                            if ((validatedName == null))
                            {
                                csentry[LEGACY_EXCHANGE_DN].Value = adminGroup + "/cn=" + System.Guid.NewGuid().ToString();
                            }
                            else
                            {
                                csentry[LEGACY_EXCHANGE_DN].Value = adminGroup + "/cn=" + validatedName + "-" + System.Guid.NewGuid().ToString();
                            }
                        }
                    }
                    else
                    {
                        //
                        // Try to rename the object
                        //
                        if (!csentry.DN.Equals(dn))
                        {
                            //LoggingCs.Log("Renaming " + dn.ToString());
                            csentry.DN = dn;
                        }
                    }
                    successful = true;
                } catch (MissingParentObjectException ex) {
                    //
                    // Typically the admin has to perform a full/delta import
                    // on the target CD, or disable provisioning until all
                    // forests are imported.
                    //
                    //LoggingCs.Log("Target MA " + MA.Name + " is not imported yet. " + "Please disable provisioning until all forests " + "are imported.");
                    throw ex;
                } catch (ObjectAlreadyExistsException ex) {
                    //
                    // If adding connector, throw away the instance to start over
                    //
                    if (provisioningAdd)
                    {
                        csentry = null;
                    }

                    //
                    // There is a duplicate object in the target AD,
                    // change the cn accordingly to avoid conflict.
                    //
                    if (!extendedNameTried)
                    {
                        extendedNameTried = true;
                        try {
                            if (mventry[DEPARTMENT].IsPresent)
                            {
                                extendedName = mventry[DEPARTMENT].Value;
                            }
                        } catch (NoSuchAttributeInObjectTypeException ex2) {
                        }
                    }

                    cn = null;
                    if (extendedName != null)
                    {
                        cn           = mventry[COMMON_NAME].Value + " (" + extendedName + ")";
                        extendedName = null;

                        if (cn.Length > AD_RDN_MAX_SIZE)
                        {
                            //
                            // If too long, we'll try without it
                            //
                            cn = null;
                        }
                    }


                    if (null == cn)
                    {
                        cn = mventry[COMMON_NAME].Value;

                        //
                        // To make sure that the number appended
                        // will not be truncated.
                        // The 2 spaces reserved is for "()"
                        //
                        cnLengthMax = AD_RDN_MAX_SIZE - (numberToAppend.ToString().Length + 2);
                        //
                        // If it's too long, we are going to truncate the
                        // name and preserve the number appended.
                        //
                        if (cn.Length > cnLengthMax)
                        {
                            cn = cn.Substring(0, cnLengthMax);
                        }

                        cn             = cn + "(" + numberToAppend.ToString() + ")";
                        numberToAppend = numberToAppend + 1;

                        if (numberToAppend > RETRY_NUM_LIMIT)
                        {
                            LogAndThrowUnexpectedDataException("Retry for " + mventry[COMMON_NAME].Value + " exceeds limit " + numberToAppend.ToString());
                        }
                    }
                }
            } while (!successful);
        }
Пример #19
0
        public void Provision(MVEntry mventry)
        {
            Tracer.TraceInformation("enter-provision");

            if (!this.EngineRules.ContainsKey(mventry.ObjectType))
            {
                return;
            }

            try
            {
                HashSet <string> executedMAs = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                foreach (Rule rule in this.EngineRules[mventry.ObjectType])
                {
                    if (executedMAs.Contains(rule.TargetManagementAgentName))
                    {
                        // skip rule as we have already executed something for this MA and connector
                        continue;
                    }

                    Tracer.TraceInformation("start-rule '{0}' (MA: {1}, type: {2}, reference: {3})", rule.Name, rule.TargetManagementAgentName, rule.Type, rule.ExternalReferenceId);
                    //Tracer.TraceInformation("{0}, displayname: {1}, mvguid: {2}", mventry.ObjectType, mventry["displayName"].IsPresent ? mventry["displayName"].Value : "n/a", mventry.ObjectID);
                    Tracer.TraceInformation("{0}, mvguid: {1}", mventry.ObjectType, mventry.ObjectID);
                    ConnectedMA ma = mventry.ConnectedMAs[rule.TargetManagementAgentName];

                    if (ma.Connectors.Count == 0)
                    {
                        // If we don't have any connectors, the only rule that can
                        // apply is a provisioning rule

                        if (rule.Action == RuleAction.Provision)
                        {
                            if (this.ConditionsApply(null, mventry, rule.Conditions))
                            {
                                if (rule.Type == RuleType.Default)
                                {
                                    this.CreateConnector(ma, mventry, rule);
                                }
                                else if (rule.Type == RuleType.External)
                                {
                                    InvokeExternalMethod(rule.ExternalReferenceId, ExternalType.Provision, mventry, null);
                                }
                                // Don't need to process any more rules
                                // as we have just newly provisioned
                                executedMAs.Add(ma.Name);
                                continue;
                            }
                        }
                        else
                        {
                            // The rule isnt a provisioning rule, and there are no connectors
                            // so there is nothing to do - skip to the next rule
                            continue;
                        }
                    }
                    else
                    {
                        // There is at least one connector, so lets see if we should
                        // re-provision, deprovision, rename, or deprovision all

                        if (rule.Action == RuleAction.Rename)
                        {
                            bool hasRenamed = false;

                            foreach (CSEntry renameCandidate in ma.Connectors)
                            {
                                if (this.ConditionsApply(renameCandidate, mventry, rule.ConditionalRename.Conditions))
                                {
                                    if (rule.Type == RuleType.Default)
                                    {
                                        this.ConditionalRenameConnector(ma, renameCandidate, mventry, rule);
                                    }
                                    else if (rule.Type == RuleType.External)
                                    {
                                        InvokeExternalMethod(rule.ExternalReferenceId, ExternalType.Provision, mventry, null);
                                    }
                                    hasRenamed = true;
                                }
                            }

                            if (hasRenamed)
                            {
                                executedMAs.Add(ma.Name);
                                continue;
                            }
                        }
                        else if (rule.Action == RuleAction.Provision)
                        {
                            // We already have a connector, so check if we need to re-provision

                            if ((rule.Reprovision != null) && (rule.Reprovision.ReprovisionEnabled))
                            {
                                Tracer.TraceInformation("check-reprovisioning-conditions");
                                if (rule.Reprovision.Conditions == null)
                                {
                                    continue;
                                }

                                bool hasReproved = false;

                                foreach (CSEntry reprovCandidate in ma.Connectors.OfType <CSEntry>().ToList())
                                {
                                    if (rule.Reprovision.Conditions.Met(mventry, reprovCandidate))
                                    {
                                        if (rule.Type == RuleType.Default)
                                        {
                                            Tracer.TraceInformation("Reprovisioning '{0}' using rule id '{1}'", reprovCandidate.DN, rule);
                                            this.DeprovisionConnector(ma, reprovCandidate, mventry, rule);
                                            this.CreateConnector(ma, mventry, rule);
                                        }
                                        else if (rule.Type == RuleType.External)
                                        {
                                            InvokeExternalMethod(rule.ExternalReferenceId, ExternalType.Provision, mventry, null);
                                        }
                                        hasReproved = true;
                                    }
                                }

                                if (hasReproved)
                                {
                                    executedMAs.Add(ma.Name);
                                    continue;
                                }
                            }
                        }
                        else if (rule.Action == RuleAction.Deprovision)
                        {
                            bool hasDeleted = false;
                            foreach (CSEntry deprovCandidate in ma.Connectors.OfType <CSEntry>().ToList())
                            {
                                if (!this.ConditionsApply(deprovCandidate, mventry, rule.Conditions))
                                {
                                    continue;
                                }

                                if (rule.Type == RuleType.Default)
                                {
                                    this.DeprovisionConnector(ma, deprovCandidate, mventry, rule);
                                }
                                else if (rule.Type == RuleType.External)
                                {
                                    InvokeExternalMethod(rule.ExternalReferenceId, ExternalType.Provision, mventry, null);
                                }
                                hasDeleted = true;
                            }

                            if (hasDeleted)
                            {
                                executedMAs.Add(ma.Name);
                                continue;
                            }
                        }
                        else if (rule.Action == RuleAction.DeprovisionAll)
                        {
                            foreach (CSEntry deprovCandidate in ma.Connectors.OfType <CSEntry>().ToList())
                            {
                                if (!this.ConditionsApply(deprovCandidate, mventry, rule.Conditions))
                                {
                                    continue;
                                }
                                if (rule.Type == RuleType.Default)
                                {
                                    mventry.ConnectedMAs.DeprovisionAll();
                                }
                                else if (rule.Type == RuleType.External)
                                {
                                    InvokeExternalMethod(rule.ExternalReferenceId, ExternalType.Provision, mventry, null);
                                }
                                break;
                            }
                        }
                        else
                        {
                            Tracer.TraceError("invalid-action-specified {0}", rule.Action);
                        }
                    }

                    Tracer.TraceInformation("end-rule {0}", rule.Name);
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("error {0}", ex.GetBaseException());
                throw;
            }
            finally
            {
                Tracer.TraceInformation("exit-provision");
            }
        }