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");
            }
        }
示例#2
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");
            }
        }
        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");
            }
        }
        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();
                    }
                }
            }
        }
示例#5
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);
        }