Step 5: Create and Configure Extensible Connectivity 2.0 MA

Creating and configuring the Extensible Connectivity 2.0 Management Agent test lab consists of the following:

  • Create the schema template file

  • Create the new management agent binary

  • Create the new File-based Management Agent

  • Create the run profiles for the new File-based management agent

  • Create the full import and delta import xml files.

Create the schema template file

The schema template file is used to define the schema for our file-based management agent.

To create the schema template file

  1. Log on to FIM1 as CORP\Administrator.

  2. Click Start, select All Programs, select Accessories and double-click Notepad.

  3. In the blank notepad that opens up, copy the code below into it.

    objectclass,delta,anchor-attribute,name,email
    
  4. At the top, click File, select Save As, navigate to C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData, in the box next to File Name: enter sample_schema.txt and click Save.

  5. Close Notepad.

Create the new management agent binary

Now we will create our new binary for our management agent. This will be done using the code provided.

To create the new management agent binary

  1. Log on to FIM1 as CORP\Administrator.

  2. Click Start, select All Programs, select Microsoft Forefront Identity Manager and double-click Synchronization Service.

  3. In the Synchronization Service, at the top, select Management Agents.

  4. At the top, select Actions, select Create Extension Projects, and choose Extensible Connectivity 2.0 Extension. This will open a Create Extension Project dialog box.

  5. In the Create Extension Project dialog box, next to Programming Language: select Visual C#

  6. In the Create Extension Project dialog box, next to Visual Studio Version: select Visual Studio 2010.

  7. In the Create Extension Project dialog box, next to Project Name: enter FileBasedECMA2Example.

  8. Create Extension Project

  9. Click OK. This will launch Visual Studio 2010.

  10. Because this is the first time running Visual Studio you will receive a Choose Default Environmental Settings Dialog box. Select General Development Settings and click Start Visual Studio.

  11. On the right, at the top, under the Solutions Explorer, double-click FileBasedECMA2Example.cs. This will open the file with code that has already been written.

  12. Open Extension Project

  13. In the code, at the top, add using System.Collections.Generic and using System.Collections.ObjectModel. The code should look similar to below:

    using System;
    using System.IO;
    using System.Xml;
    using System.Text;
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.MetadirectoryServices;
    
    namespace FimSync_Ezma
    
  14. In the code, at the top, un-remark the following interfaces: IMAExtensible2FileImport, IMAExtensible2FileExport, IMAExtensible2GetCapabilities, and IMAExtensible2GetParameters. The code should look similar to the code below:

    namespace FimSync_Ezma
    {
        public class EzmaExtension :
        //IMAExtensible2CallExport,
        //IMAExtensible2CallImport,
        IMAExtensible2FileImport,
        IMAExtensible2FileExport,
        //IMAExtensible2GetHierarchy,
        //IMAExtensible2GetSchema,
        IMAExtensible2GetCapabilities,
        IMAExtensible2GetParameters
        //IMAExtensible2GetPartitions
        {
    
  15. Now, down below the constructor, add the following code to implement the Management Agents capabilities.

    public EzmaExtension()
            {
                //
                // TODO: Add constructor logic here
                //
            }
    
            public MACapabilities Capabilities
            {
                get
                {
                    MACapabilities myCapabilities = new MACapabilities();
    
                    myCapabilities.ConcurrentOperation = true;
                    myCapabilities.ObjectRename = false;
                    myCapabilities.DeleteAddAsReplace = true;
                    myCapabilities.DeltaImport = true;
                    myCapabilities.DistinguishedNameStyle = MADistinguishedNameStyle.None;
                    myCapabilities.ExportType = MAExportType.AttributeUpdate;
                    myCapabilities.NoReferenceValuesInFirstExport = false;
                    myCapabilities.Normalizations = MANormalizations.None;
    
                    return myCapabilities;
                }
            }
    
  16. Now, below the management agent’s capabilities, add the following method to implement the parameters of our management agent.

            public IList<ConfigParameterDefinition> GetConfigParameters(KeyedCollection<string, ConfigParameter> configParameters,
                                                                 ConfigParameterPage page)
            {
                List<ConfigParameterDefinition> configParametersDefinitions = new List<ConfigParameterDefinition>();
    
                switch (page)
                {
                    case ConfigParameterPage.Connectivity:
    
    
                        break;
    
    
                    case ConfigParameterPage.Global:
    
                       configParametersDefinitions.Add(ConfigParameterDefinition.CreateStringParameter("Full Import File", ""));
                       configParametersDefinitions.Add(ConfigParameterDefinition.CreateStringParameter("Delta Import File", ""));
                       configParametersDefinitions.Add(ConfigParameterDefinition.CreateStringParameter("Export File", ""));
                       configParametersDefinitions.Add(ConfigParameterDefinition.CreateDropDownParameter("Export Encoding", "ASCII,Unicode,UTF8", false, "UTF8"));
                        break;
    
                    case ConfigParameterPage.Partition:
                        break;
    
                    case ConfigParameterPage.RunStep:
                        configParametersDefinitions.Add(ConfigParameterDefinition.CreateCheckBoxParameter("Omit Xml Declaration", false));
                        break;
                }
    
                return configParametersDefinitions;
            }
    
  17. Now, below the GetConfigParameter method, add the following code to implement the ValidateConfigParameters method.

            public ParameterValidationResult ValidateConfigParameters(KeyedCollection<string, ConfigParameter> configParameters,
                                                                       ConfigParameterPage page)
            {
    
    
                ParameterValidationResult myResults = new ParameterValidationResult();
                return myResults;
    
            }
    
  18. Now, below the ValidateConfigParameters method, add the following code to implement the WriteImportFileResults method. This method will read from our XML file and write the results to our intermediary file which is specified in the run profile.

    public WriteImportFileResults WriteImportFile(
                                                 KeyedCollection<string, ConfigParameter> configParameters,
                                                 Schema types,
                                                 WriteImportFileRunStep importRunStep)
            {
                //
                // Write out the delimited file.
                //
                StreamWriter swImport = new StreamWriter(importRunStep.FilePath, true);
    
                swImport.WriteLine(
                  "{0},{1},{2},{3},{4}",
                  "objectclass",
                  "delta",
                  "anchor-attribute",
                  "name",
                  "email"
                  );
    
                string inputxml = "";
                XmlDocument doc = new XmlDocument();
    
                if (importRunStep.ImportType == OperationType.Full)
                {
                    inputxml = MAUtils.MAFolder + @“\” + configParameters["Full Import File"].Value;
    
                }
    
                if (importRunStep.ImportType == OperationType.Delta)
                {
                    inputxml = MAUtils.MAFolder + @“\” + configParameters["Delta Import File"].Value;
                }
    
                doc.Load(inputxml);
    
                XmlNodeList xnList = doc.SelectNodes("/sample-objects/object");
    
                foreach (XmlNode node in xnList)
                {
    
                    string objectclass = node["objectclass"].InnerText;
                    string delta = node["delta"].InnerText;
                    string anchor = node["anchor-attribute"].InnerText;
                    string name = node["name"].InnerText;
                    string email = node["email"].InnerText;
    
                    string fullline = objectclass + "," + delta + "," + anchor + "," + name + "," + email;
                    swImport.WriteLine(fullline);
                }
    
                swImport.WriteLine();
    
                swImport.Close();
    
                return new WriteImportFileResults();
            }
    
  19. Now, below the WriteImportFileResults method, add the following code to implement the ReadExportFile method. This method will read from our intermediary file which is specified in the run profile and write the results to an XML file.

    public void ReadExportFile(KeyedCollection<string, ConfigParameter> configParameters,
                                         Schema types,
                                         ReadExportFileRunStep exportRunStep)
            {
                XmlWriter m_xmlWriterExport;
    
                StreamReader sr = new StreamReader(exportRunStep.FilePath);
                string lineContents = null;
    
                XmlWriterSettings xmlSettings = new XmlWriterSettings();
    
                // Determine encoding from Configuration Parmeters
                string encoding = configParameters["Export Encoding"].Value;
                if (encoding.Equals("ASCII"))
                {
                    xmlSettings.Encoding = Encoding.ASCII;
                }
                else if (encoding.Equals("UTF8"))
                {
                    xmlSettings.Encoding = Encoding.UTF8;
                }
                else
                {
                    xmlSettings.Encoding = Encoding.Unicode;
                }
    
                // Use a run step config paramater to control Xml declaration
                string omitXmlDecl = configParameters["Omit Xml Declaration"].Value;
                if (omitXmlDecl.Equals("1"))
                {
                    xmlSettings.OmitXmlDeclaration = true;
                }
    
                // Begin XML file
                string exportfile = configParameters["Export File"].Value.ToString();
                m_xmlWriterExport = XmlTextWriter.Create(MAUtils.MAFolder + @"\" + exportfile, xmlSettings);
                m_xmlWriterExport.WriteStartElement(Nodes.Root);
                m_xmlWriterExport.WriteAttributeString(Nodes.FullExport, (OperationType.Full == exportRunStep.ExportType) ? "true" : "false");
    
                // Include partition DN
                m_xmlWriterExport.WriteElementString(Nodes.PartitionDN, exportRunStep.StepPartition.DN);
    
                // Read from export file and create XML file
                while (null != (lineContents = sr.ReadLine()))
                {
                    char[] commaEscape = new char[] { ',' };
                    char[] quoteEscape = new char[] { '"' };
                    string[] valueComponents = lineContents.Split(commaEscape);
    
                    //
                    // NOTE: In our sample, we assume that the order given to us is:
                    //  objectclass,delta,anchor-attribute,name,email
                    //
    
                    //
                    // Check the objectclass node and see if this object class is
                    // something that we are interested in.
                    //
                    if (Nodes.ObjectClass == valueComponents[0].Trim(quoteEscape))
                    {
                        continue;
                    }
    
                    //
                    // This means that we are interested in this object class.
                    // Populate the the comma-delimited file.
                    //
                    m_xmlWriterExport.WriteStartElement(Nodes.Object);
    
                    m_xmlWriterExport.WriteElementString(
                        Nodes.ObjectClass,
                        valueComponents[0].Trim(quoteEscape)
                        );
    
                    m_xmlWriterExport.WriteElementString(
                        Nodes.Delta,
                        valueComponents[1].Trim(quoteEscape)
                        );
    
                    m_xmlWriterExport.WriteElementString(
                        Nodes.Anchor,
                        valueComponents[2].Trim(quoteEscape)
                        );
    
                    m_xmlWriterExport.WriteElementString(
                        Nodes.Name,
                        valueComponents[3].Trim(quoteEscape)
                        );
    
                    m_xmlWriterExport.WriteElementString(
                        Nodes.Email,
                        valueComponents[4].Trim(quoteEscape)
                        );
    
                    m_xmlWriterExport.WriteEndElement();
                }
    
                m_xmlWriterExport.WriteEndElement();
    
                m_xmlWriterExport.Close();
            }
    
    
  20. Now, finally, at the end add the following struct Nodes code. These are used for generating our export XML file.

    struct Nodes
            {
                //
                // Struct used to keep track of the XML node names.
                // This is used when generating the XML file.
                //
                public const string Root = "sample-objects";
                public const string PartitionDN = "partition-dn";
                public const string FullExport = "full-export";
                public const string Object = "object";
                public const string ObjectClass = "objectclass";
                public const string Delta = "delta";
                public const string Anchor = "anchor-attribute";
                public const string Name = "name";
                public const string Email = "email";
            }
    
  21. At the top, select Build and choose Build Solution from the drop-down. At the bottom, in the Output window you should see Build: 1 succeeded.

    Extension Code

Create the new File-based Management Agent

Now we will create the new management agent in the synchronization service.

To create the new File-based Management Agent

  1. Back in the Synchronization Service, click Management Agents and

  2. In the Synchronization Service, at the top, select Management Agents and over on the right, under Actions, select Create. This will open a Create Management Agent wizard.

  3. On the Create Management Agent screen, next to Management Agent for: select Extensible Connectivity 2

  4. On the Create Management Agent screen, next to Name: enter FileBasedECMA2Example

    Create Management Agent

  5. Click Next.

  6. On the Select Extension DLL screen, click Browse and select FileBasedECMA2Example.dll. Click OK.

  7. On the Select Extension DLL screen, click Refresh interfaces. This will populate the box below.

    Select Extension DLL

  8. Click Next.

  9. On the Select Template Input File screen, click Browse and select navigate to the file we created earlier: C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\ sample_schema.txt.

  10. On the Select Template Input File screen, next to Code Page: select US-ASCII

  11. On the Select Template Input File screen, next to File Format: select Delimited

    Select Template Input File

  12. Click Next.

  13. On the Delimited Text Format screen, place a check in the box next to Use first row for header names.

    Delimited Text Format

  14. Click Next.

  15. On the Configure Attributes screen, click Set Anchor. This will open a Set Anchor dialog box.

  16. On the Set Anchor dialog box, select anchor-attribute and click Add>. Click OK.

    Configure Attributes

  17. Click Next.

  18. On the Define Object Types screen, click Next.

    Define Object Types

  19. On the Global Parameters screen, in the box next to Full Import File enter full_import_file.xml

    On the Global Parameters screen, in the box next to Delta Import File enter delta_import_file.xml

    On the Global Parameters screen, in the box next to Export File enter export_file.xml

    On the Global Parameters screen, on the drop-down next to Export Encoding select ASCII

    Global Parameters

  20. Click Next.

  21. On the Configure Partitions and Hierarchies screen, click Next.

    Configure Partitions and Hierarchies

  22. On the Configure Connector Filter screen, click Next.

    Configure Connector Filter

  23. On the Configure Join and Projection Rules screen, click New Projection Rule. This will open a Projection dialog box.

  24. On the Projection dialog box, verify Declared is selected.

  25. On the Projection dialog box, verify Person is in the box next to Metaverse object type.

  26. Click OK.

  27. Click Next.

    Configure Join and Projection Rules

  28. On the Configure Attribute Flow screen, from the drop-down list under Data source object type, select Person.

  29. On the Configure Attribute Flow screen, from the drop-down list under Metaverse object type list, select person.

  30. On the Configure Attribute Flow screen, for Mapping Type, select Direct.

  31. On the Configure Attribute Flow screen, from the list below Data source attribute, select email.

  32. On the Configure Attribute Flow screen, from the list below Metaverse attribute, select mail.

  33. On the Configure Attribute Flow screen, for Flow Direction, select Import. Ensure that Allow Nulls is not selected. Click New.

  34. Repeat the above steps for each of the attribute entries in the following table.

    Important

    Be sure to change the Flow Direction where applicable. Also ensure that Allow Nulls is not checked.

    Table 1 – Attribute Flow

    Data Source Attribute Flow Direction Metaverse attribute

    email

    Import

    mail

    anchor-attribute

    Import

    employeeID

    name

    Import

    displayName

    name

    Import

    accountName

    name

    Export

    accountName

    email

    Export

    mail

    Configure Attribute Flow

  35. Click Next.

  36. On the Configure Deprovisioning screen, click Next.

    Configure Deprovisioning

  37. On the Configure Extensions screen, place a check in Enable password management.

    Configure Extensions

  38. Click Finish.

Create the run profiles for the new File-based management agent

Now that the File-based management agent has been created, you will need to create run profiles for the management agent.

To create the run profiles for the new File-based management agent

  1. First, move the sample_full_import.csv file into C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\FileBasedECMA2Example

  2. Now, back in the Synchronization Service, on the right of the portal page, under Actions menu, click Configure Run Profiles. This opens the Configure run Profiles window.

  3. Click New Profile. This will begin the Configure Run Profile wizard.

  4. On the Profile Name page, in the text box under Name, type the following, and then click Next:
    Full Import

  5. On the Configure Step page, from the drop-down list under Type, select Full Import (Stage Only), and then click Next.

  6. On the Management Agent Configuration page, next to Input file name: enter fullimport.txt. Place a check in Delete file after successful run. Click Next.

  7. Click Finish.

  8. Click New Profile.

  9. On the Profile Name page, in the text box under Name, type the following, and then click Next:
    Delta Import

  10. On the Configure Step page, from the drop-down list under Type, select Delta Import (Stage Only), and then click Next.

  11. On the Management Agent Configuration page, next to Input file name: enter deltaimport.txt. Place a check in Delete file after successful run. Click Next.

  12. Click Finish.

  13. Click New Profile.

  14. On the Profile Name page, in the text box under Name, type the following text, and then click Next:
    Export

  15. On the Configure Step page, from the drop-down list under Type, select Export, and then click Next.

  16. On the Management Agent Configuration page, next to Output file name: enter export.txt. Place a check in Delete file after successful run. Click Next.

  17. Click Finish.

  18. Click New Profile.

  19. On the Profile Name page, in the text box under Name, type the following text, and then click Next:
    Full Synchronization

  20. On the Configure Step page, from the drop-down under Type, select Full Synchronization, and then click Next.

  21. On the Management Agent Configuration page, click Finish.

  22. Click Apply, and then click OK.

Create the full import and delta import xml files.

In this section we will create our full import and delta import xml files.

To create the full import XML file

  1. Copy the following text, and then paste it into a new Notepad file.

    <sample-objects>
        <object>
            <objectclass>Person</objectclass>
            <delta>Add</delta>
            <anchor-attribute>1</anchor-attribute>
            <name>Object1</name>
            <email>Object1@corp.contoso.com</email>
        </object>
        <object>
            <objectclass>Person</objectclass>
            <delta>Add</delta>
            <anchor-attribute>2</anchor-attribute>
            <name>Object2</name>
            <email>Object2@corp.contoso.com</email>
        </object>
    </sample-objects>
    
  2. Save the Notepad file on your local drive as C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\FileBasedECMA2Example\full_import_file.xml

To create the delta import XML file

  1. Copy the following text, and then paste it into a new Notepad file.

    <sample-objects>
        <object>
            <objectclass>Person</objectclass>
            <delta>Modify</delta>
            <anchor-attribute>1</anchor-attribute>
            <name>Object1</name>
            <email>newemail@corp.contoso.com</email>
        </object>
    </sample-objects>
    
  2. Save the Notepad file on your local drive as C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\MaData\FileBasedECMA2Example\delta_import_file.xml