Windows PowerShell is a new command-line shell and scripting environment intended for system administrators. Part of Microsoft .NET technology, PowerShell allows you to manage and configure any aspect of Windows.
The Scripting driver provides a complete Windows PowerShell API for interacting with identity management systems whose tools (including APIs) are available on Windows. The Identity Vault and Identity Manager can run on any supported operating system. Identity Manager can communicate with any supported system on which the driver is installed via an encrypted network connection.
Before beginning script development, review the preceding topics in this section for information on defining what data is synchronized between identity management systems.
With additional development work, the driver can also be adapted to support any scripting language that supports command line operation.
Developing a custom driver with PowerShell is discussed in this section. Topics include
To change the data in your external application, you need to know how to use the application’s tools or API (Application Programming Interface). These tools must provide automated operation and not require user input.
Applications often include command-line tools. These tools are manually executed from the Windows command prompt, and they can be executed from scripts. For example, suppose an application provides a tool to add identities with a program called appadd.exe.
appadd -n "Bob Smith" -t "818-555-2100"
This command adds an identity named “Bob Smith” with the specified phone number. The strings following the program name are called parameters or arguments. Because PowerShell is a command shell, commands can be executed by the script code:
$name = "Bob Smith $phone = "818-555-2100" appadd -n $name -t $phone $exitcode = $LASTEXITCODE
You can use the pipeline to send data to a program’s standard input and to receive output from the program’s standard output and standard error.
# Create an array with two lines $inlines = "USERNAME=Bob Smith", "TELEPHONE=818-555-2100" $inlines | appadd | Set-Variable outlines
PowerShell will output the contents of the inlines array to appadd’s standard input, one item per line. The (standard) output will be stored in outlines, as a single string variable for one line or an array for more than one line. (You don't use the $ character with the Set-Variable cmdlet.)
Thus, with command-line tools, you can construct the command line’s parameters using the values passed to the script, then execute the program.
Another way to modify application data is through Windows COM (Common Object Model) or .NET objects. Consult your application’s documentation to see whether it exposes any COM or .NET objects. These objects can be loaded directly in PowerShell:
$appobject = New-Object -comobject MyApplication.MyObject $appobject.AddIdentity("Bob Smith", "818-555-2100")
Note that there are no guarantees regarding types and availability of tools. You must determine if sufficient tools are provided by the application. If they are not, you can contact the application’s developers and request them.
Make a list of the tools that can be used for each event type. The application might provide multiple tools or a single program that can be used for any event type.
You also need to determine what tools are available for monitoring event changes in the application. The Scripting driver works on a polling system. It periodically calls a polling script to determine what has changed in the external application. Here are some ideas for monitoring changes:
The first time the polling script is run, a list of identities and relevant attributes is read from the application using an application-provided tool. This list is stored as a file. On subsequent polls, a new list is generated and compared to the old list. Any differences are submitted as events to the driver.
The application provides a tool that allows you to request all identities that have changed after a certain point in time. The polling script requests events that have occurred since the previous poll.
The application allows a script to be run when an event occurs. You write a script that stores the event data into a file. When the (Scripting driver) polling script runs, it consumes this file and submits the data as an event to the driver.
Monitoring the application’s changes might be the most difficult aspect of developing your driver. You must study your application’s tools to determine the best way to achieve synchronization.
At this point you should have a list of what data will be synchronized, how events will be handled, and what application tools are available. It is time to develop the heart of your driver in policies and scripts.
Many types of tasks can be handled in driver policies. You can import the driver configuration provided with the Scripting driver, and then edit policies in Novell iManager. You can also edit policies and simulate their operation in Novell Designer. The extensive functionality of policies is outside the scope of this document, so you should refer to your Novell Identity Manager 3.6.1 Policy guides for help.
Tasks that don’t interact with the external application might be more suited to policies. On the other hand, if you are more familiar with your scripting language than policies, you can develop your driver more quickly by using scripts.
Event data is submitted to the scripts in name/value pair format. This format consists of lines containing a name, an equal sign (=) and a value. Therefore, each line is a name/value pair. Each name/value pair is unique, but there can be multiple name/value pairs with identical names but different values.
ASSOCIATION=BobUser ADD_TELEPHONE=818-555-2100 ADD_TELEPHONE=818-555-9842
You typically don’t have to worry about the format. The script library provides functions for retrieving event data.
After all policy processing is complete, Identity Manager submits the event in XML format to the driver shim. The driver shim submits the event data to the scripts.
In the default Scripting driver, the script Subscriber.ps1 in the scripts folder is called. This script does some preliminary processing, and then calls a routine from an included script. The included scripts correspond to the Subscriber event types: Add.ps1, Modify.ps1, ModifyPassword.ps1, Delete.ps1, Rename.ps1, Move.ps1, and Query.ps1.
For each event type, you should retrieve the information you need from the event data, submit changes to the external application using application-provided tools and return a status (such as success or failure) to Identity Manager.
Event data is retrieved primarily using the idm_geteventvalues function. This function returns an array of values corresponding to the name specified as the function’s parameter. (idm_geteventvalue is available for single-valued items.) The following table shows many item names.
Table 5-26 Item Names
The association value indicates which identity has been changed. If the identity has no association, an association must be generated for it using an implementation-specific rule that you have adopted. When Identity Manager processes an event for an identity with no association, it executes the driver’s Matching policy. This policy attempts to match the event’s identity to an identity on the external application’s system. Doing this usually involves executing a query. The default Matching policy included with the Scripting driver queries for matching Users and Groups based on the CN attribute. If the event’s identity matches an identity on the external application, both identities must be assigned the new association. Assigning this association can be included as part of the query-handling script. (Handling queries is discussed in Handling Query Events.) If no identity matches, an Add event is issued, and the new association can be assigned as part of the Add event-handling script:
idm_setcommand "ADD_ASSOCIATION" idm_writevalue "ASSOCIATION" $my_association (etc.)
The example above also illustrates the idm_setcommand function. This function sets a command value that indicates what action Identity Manager should perform. The ADD_ASSOCIATION command assigns an association to an identity, as discussed above. The Subscriber can also issue MODIFY_ASSOCIATION and REMOVE_ASSOCIATION commands.
On the Subscriber channel, you often do not need Identity Manager to perform an action, but simply need to report a status. The IDMStatus subroutines noted below can be used to indicate a status to Identity Manager. They take a message to be logged as the parameter.
Table 5-27 Subroutines
idm_setcommand and the status functions must be issued before specifying values with idm_writevalues. idm_writevalues (or its single-valued version idm_writevalue) is used to set values to return to Identity Manager. It is passed a value name and an array of values. In the ADD_ASSOCIATION example above, idm_writevalue is used to set the ASSOCIATION value. You can specify values for items listed in the table above.
For Query events, Identity Manager submits values that define the parameters of a search of the external application’s identity management system. Queries are usually issued from the policies you have defined for your system. The table below specifies values that can be specified in queries. Not all values are relevant to your external application.
Table 5-28 Query Values
Execute the query against the external application using application-provided tools. Then return each identity by setting an INSTANCE command, followed by relevant values from the list below.
Table 5-29 Query Values
After returning all identities, call idm_statussuccess to indicate a successful query.
Below is a more detailed summary of the actions to take for a non-Query event.
Gather information about the event using idm_geteventvalues. Return a warning or error if there is a problem.
Submit the event data to the external application using application-provided tools.
Set a command using idm_setcommand and/or a status with the idm_status subroutines, based on the result of the event.
Set event values with idm_writevalues.
If you have not already done so, set a status with an idm_status subroutine.
Below is an example of the Add.ps1 script, which forms an association from an identity’s CN and class name, and uses a hypothetical tool called appadd.
function idm_add { $classname = idm_geteventvalue "CLASS_NAME" $cn = idm_geteventvalue "CN" $phone = idm_geteventvalue "Telephone" if ($classname -eq "" -or $cn -eq "") { idm_statuserror "Add event: missing CLASS_NAME and/or CN" } else { appadd -n "$cn" -t "$phone" if ($LASTEXITCODE -eq 0) { idm_setcommand "ADD_ASSOCIATION" idm_writevalue "ASSOCIATION" "$cn$classname" idm_writevalue "DEST_DN" (idm_geteventvalue "SRC_DN") idm_statussuccess "Add event succeeded" } else { idm_statuserror "Add event failed with error code $LASTEXITCODE" } } }
Handling a query is similar, except you return INSTANCE items rather than use other commands. Below is an example Query.ps1 that searches an external application for a telephone number. It uses a hypothetical tool called appsearch.
function idm_query { $searchname = idm_geteventvalue "SEARCH_ATTR_CN" if ($searchname -eq "") { idm_statuserror "Query: no search value" } else { # the telephone number is output from the application appsearch -n "$searchname" | Set-Variable phone if ($phone -ne $null) { idm_setcommand "INSTANCE" idm_writevalue "CLASS_NAME" (idm_geteventvalue "CLASS_NAME") idm_writevalue "ASSOCIATION" (idm_geteventvalue "ASSOCIATION") idm_writevalue "ATTR_Telephone" $phone idm_statussuccess "Query succeeded" } else { # Return success with no results idm_statussuccess "Query succeeded (no matches)" } } }
Events that occur on the external application are submitted to Identity Manager on the Publisher channel. The Scripting driver periodically polls the external application for events. How this poll detects events is implementation-specific and must be defined by the user.
The driver calls Poll.ps1 to detect application events. Poll.ps1 should be implemented as follows:
Use application-provided tools to detect events in your application.
For each event:
Call the idm_publishinit function to set the appropriate command.
Call idm_publishvalues to set event values.
Call idm_publish to submit the event to Identity Manager.
If there were events, call an idm_status function to report the status.
idm_publishinit takes a command name as its single parameter. Below is a list of valid command names for idm_publishinit.
Table 5-30 Command Names
Below is an example of a Poll.ps1 that checks for a password change. It uses a hypothetical application tool called apppwd.
apppwd --changes | Set-Variable results foreach ($result in $results) { # Entries are in the format "association=password" $tokens = $result.split("=") $association = $tokens[0] $password = $tokens[1] idm_publishinit "MODIFY_PASSWORD" idm_publishvalue "ASSOCIATION" $association idm_publishvalue "PASSWORD" $password idm_publish next idm_statussuccess "Poll succeeded"
Events submitted using idm_publish are processed through your driver’s Publisher channel policies. See the Novell Identity Manager 3.6.1 Policy guides for more information.
Another script executed in the Publisher Channel is Heartbeat.ps1. This script is executed when the Publisher channel is idle for the interval specified in the driver parameters. (You may also set the interval to 0 so no heartbeat is issued.) You can use the heartbeat to check the availability of the external system or do “idle state” tasks. The idm_heartbeatsuccess, idm_heartbeatwarning, and idm_heartbeaterror subroutines can be used to indicate the result of the heartbeat. Below is an example based on a hypothetical tool called apphealth.
apphealth if ($LASTEXITCODE -eq 0) { idm_heartbeatsuccess "Heartbeat succeeded" } else { idm_heartbeaterror "Heartbeat failed with error code $LASTEXITCODE" }
The response to the heartbeat is implementation-dependent, and can be defined in policies or in the script itself. You could send a message to auditing using Novell Audit. You could store a value in a file and have Subscriber scripts read the file and call idm_statusretry if they find that value in the file.
A driver has values known as driver parameters. The driver parameters are divided into driver settings applicable to the whole driver, and Subscriber and Publisher settings for their respective channels. The idm_getdriverparam, idm_getsubscriberparam, and idm_getpublisherparam functions can be used to retrieve these values. The table below shows parameters in the default Scripting driver. Other parameters can be added to the driver’s XML Configuration file (see “Managing Identity Manager Drivers” in the Novell Identity Manager 3.6.1 Administration Guide).
Table 5-31 Driver Parameters
In the following example, a script retrieves the Publisher polling interval.
$pollinginterval = idm_getpublisherparam("pub-polling-interval")
Scripts might need to retrieve information from the Identity Vault. They can do this by issuing a query.
Initialize the query with idm_queryinit.
Set query search parameters using functions listed below.
Execute the query with idm_doquery.
Read the result (instance) using functions listed below.
This table lists functions for setting query search parameters.
Currently query support is limited. It will only return one instance based on the specified association or DN. (If both association and DN are specified, association is used.) The functions below allow you to retrieve information from the instance.
Following is an example of a query of the Identity Vault that retrieves the address and ZIP code for users living in Provo, Utah.
idm_queryinit idm_setqueryassociation (idm_geteventvalue "ASSOCIATION") idm_addsearchattr "City" "Provo" idm_addsearchattr "S" "UT" # State idm_addreadattr "SA" # Street Address idm_addreadattr "Postal Code" $result = idm_doquery if ($result) { $address = idm_querygetinstanceattrvalue "SA" $zipcode = idm_querygetinstanceattrvalue "Postal Code" # ... etc. ... }
The function idm_trace allows you to write a message to the Script Trace File specified in the Driver Parameters. Tracing is useful for script debugging and auditing.
idm_trace "Trace message"
If the driver shim is being run as a Windows Service, all output from scripts will also be recorded in the Script Trace File.
When developing scripts, you may need to do some debugging to track down problems. The following list indicates some facilities for debugging.
The driver traces activity to its Trace file (logs\trace.log by default). The trace level setting in conf\wsdrv.conf controls how much debugging is written to the log.
The trace level is set using the -trace option in wsdrv.conf, for example, -trace 9.
You can view the trace file through a Web browser:
Use a Web browser to access the driver shim at https://driver-address:8091. Substitute the DNS name or IP address of your driver for driver-address.
Authenticate by using any user name and the password that you specified as the Remote Loader password.
Click
.The idm_trace function described above writes output to the trace file specified in the driver parameters (logs\script-trace.log by default).
The eDirectory tool DSTrace can be used to monitor Identity Manager activity. Set the tracing level for the driver in iManager. DSTrace shows the XML documents being submitted to the driver for events, and how Policies are evaluated. It also shows the status and message for each event.
The Status Log is written to logs\dirxml.log. It shows a summary of the events that have been recorded on the Subscriber and Publisher channels.
You can view the Status Log through a Web browser:
Use a Web browser to access the driver shim at https://driver-address:8091. Substitute the DNS name or IP address of your driver for driver-address.
Authenticate by using any user name and the password that you specified as the Remote Loader password.
Click
.While it is best to run the driver as a service in production environments, you can run wsdriver.exe as a standard program. When you do so, a console window displays trace messages (see above) for the driver. Also, text written to standard output from scripts is displayed in this window.
The Scripting driver is installed by using a setup program. See Section 3.2, Installing the Windows Scripting Driver for information on installing the default driver.
To deploy your custom driver, the end user should first run the Windows Scripting driver installation program provided by the installation media (see Section 3.2, Installing the Windows Scripting Driver). This program installs core files needed by the driver. Then your custom driver files can be deployed easily, whether through an installation program or an archive file. The table below shows the directory structure below the installation directory and what files are installed.
Table 5-32 Directory Structure and Files
If you are using an installation program, you can obtain the driver’s installation path from the following registry value:
HKEY_LOCAL_MACHINE\SOFTWARE\Novell\Windows Script Driver\Path
Or for the x86 driver running an x64 version of Windows, use the path from the following registry value:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Novell \Windows Script Driver\Path
The formats of wsdrv.conf and schema.def can be viewed in Section 4.2, The Driver Shim Configuration File and Section 5.2, The Connected System Schema File.
If SSL encryption is desired for communication between the driver shim and Identity Manager engine, a certificate must be retrieved from the Identity Vault. Run the following command and follow the prompts to retrieve the certificate:
wsdriver.exe -s
The certificate will be stored in the keys\ directory. You must have LDAP with SSL available for the Metadirectory. When making an installation program for deployment, you might want to include this command as part of the installation:
To ensure that only authorized systems access the Metadirectory, a Driver Object password and Remote Loader password are used. Run the following command and enter the passwords at the prompts:
wsdriver.exe -sp
This action also can be incorporated into an installation program.
You should run a Scripting driver as a service. To the install the service, run the following command or include it as part of an installation program:
wsdriver.exe -installService
The service, which can then be run from the Services applet, can be removed as follows:
wsdriver.exe -removeService
You should distribute the XML configuration file that contains parameters and policies your driver needs. The user can then select it when installing your driver.