2.4.4 User Attribute Retrieval and Transformation

The User Attribute Retrieval and Transformation feature enables you to retrieve an attribute from an external data source and transform it before sending it in an assertion. The data source can be any database, REST web service, or LDAP repositories. You can transform a user’s local attributes, LDAP attributes, Shared Secrets, and various profiles, such as Personal Profile and Employee Profile.

You can use virtual attributes to generate dynamic data at runtime from the current values of the user attributes. The transformed attribute values are not stored in any persistent data stores. They are in the memory as part of user’s session.

Prerequisites

To perform complex user attribute transformations, you must have a basic understanding of JavaScript. To see sample JavaScripts with examples, see Sample JavaScripts with Examples.

How User Attribute Retrieval and Transformation Helps

User Attribute Retrieval and Transformation helps you to perform the following activities:

  • Retrieve attribute values from external sources other than the configured user stores. The sources can be external REST web service, external database, or any external LDAP repository.

  • Transform attribute values before they are sent as part of an assertion to a federated provider. For example, you can edit an attribute value before it is sent from identity provider to a service provider in a SAML 2.0 federation. You can also edit an attribute value sent from identity provider to Access Gateway used in policies.

  • Transform the attribute value used in policies. For example, you can transform Identity Server role-based policies.

User Attribute Retrieval and Transformation introduces the following configuration settings in Identity Server:

  • Data Source: An entity that holds configuration properties that help in connecting to an external data source. The properties of the data source can be defined in the data source user interface. A data source can be a REST web service, an LDAP repository, or an SQL database.

  • Attribute Source:Represents queries that fetch attributes from a data source. You can define an LDAP search filter or an SQL query. You can also define requests and configure the response to retrieve attributes from a REST web service resource endpoint.

  • Virtual Attribute: Helps you specify the attributes that must be transformed and in the way the transformations happen. A virtual attribute can transform multi-valued attributes.

Managing a Data Source

You can create, edit, or delete a data source.

NOTE:You cannot delete a data source that is being used by an attribute source.

Creating a Data Source

To create a data source, perform the following steps:

  1. Click Devices > Identity Server > Shared Settings > Data Sources.

  2. Click + to add a data source.

  3. Select one of the following data sources:

    • Rest Web Service: Continue with Step 4.

      The data source of REST web service contains only the common information that is required by the endpoints, such as base URL, setting trusted root, and authentication. If you require to retrieve attributes by using REST API calls from an external REST web service, you must add the REST web service data source.

    • Database: Continue with Step 5.

      Supported databases include Oracle and Microsoft SQL.

    • LDAP: Continue with Step 6.

      eDirectory and Active Directory are supported. You can create multiple search context and LDAP replicas.

  4. (For Database) Specify the following details:

    Field

    Description

    Database Name

    Specify the name of the database.

    Database Driver

    Select a driver from the list. The associated driver name is auto-populated. If you select Others (Unsupported), specify the driver name.

    Max Connections

    Specify the maximum number of connections. The default value 20.

    Idle TimeOut

    Specify the idle timeout. The default value is 600000 milliseconds. Set this value based on the server setting. For example, if the server timeout value is 600000, then the timeout value must not exceed 600000.

    Connection TimeOut

    Specify the connection timeout. The default value is 10000 milliseconds. Set this value based on the server setting.

    Username

    Specify the username used to read from the database.

    Password

    Specify the password used to read from the database.

    Confirm Password

    Specify the password again.

    URL

    Specify the database URL based on the database driver selected.

    Based on the database type, you need to add the corresponding jars.

    For Oracle:

    1. Download the JDBC connector for the Oracle database from Oracle.com.

    2. Copy the JDBC connector jar to the following folder:

      • Administration Console: /opt/novell/nam/adminconsole/webapps/nps/WEB-INF/lib

      • Identity Server: /opt/novell/nam/idp/webapps/nidp/WEB-INF/lib

    3. Restart Administration Console and Identity Server.

    For Microsoft SQL Server:

    1. Download the JDBC connector for the SQL Server database from Microsoft.

    2. Copy the JDBC connector jar file to the following folder:

      • Administration Console: /opt/novell/nam/adminconsole/webapps/nps/WEB-INF/lib

      • Identity Provider: /opt/novell/nam/idp/webapps/nidp/WEB-INF/lib

    3. Restart Administration Console and Identity Server.

  5. (For LDAP) Specify the following details:

    1. Specify LDAP Properties:

      Field

      Description

      LDAP Name

      Specify a display name for the LDAP database.

      Directory Type

      Select the type of directory. If you select Others (Unsupported), specify a directory name in the adjacent field: sunonedir, custom1, custom2, custom3, custom4, others.

      Username

      Specify the username used to read from the database.

      Password

      Specify the password used to read from the database.

      Confirm Password

      Specify the password again.

      LDAP Operation TimeOut

      Specify the LDAP operation timeout. The default value is 15000 milliseconds. You can set this value based on the server setting.

      Idle Connection TimeOut

      Specify the connection timeout. The default value is 10000 milliseconds. Set this value based on the server setting. For example, if the server timeout is 15000 milliseconds, then the LDAP timeout value must not exceed 15000.

    2. Specify required number of contexts under Search Contexts.

      1. Click Actions > Add Search Context.

      2. Specify Search context to locate users in the directory.

      3. Select the scope such as One level, Object, or Subtree in Scope.

        If a user exists outside of the specified search context and its scope (One level, Object or Subtree), Identity Server cannot find the user and the search fails.

      4. Click Save.

    3. Specify required number of LDAP replicas under LDAP Replicas.

      1. Click Actions > Add LDAP Replica.

      2. Specify the following details to add a LDAP replica:

        Field

        Description

        Name

        Specify a name to represent the LDAP replica.

        IP Address

        Specify the IP address of the LDAP directory.

        Port

        Specify the port number. By default, it is 389.

        For a secure connection, select Use Secure LDAP Connection. The port number changes to 636.

        You must import the trusted root if you select a secure connection. To import the trusted root, click Auto Import Trusted Root. The trusted certificate of the server will be imported to the Identity provider trust store. Update the Identity provider each time.

        Max Connections

        Specify the maximum number of connections. By default, it is set to 20.

      3. Click Save.

  6. (For REST Web Services) Specify the following details:

    Field

    Description

    Web Service Name

    Specify a display name for the web service.

    This can be any alpha-numeric name.

    Description

    (Optional) Specify the description for the web service.

    Base URL

    Specify the base URL in the <protocol>://<host>:<port> format. For example: http://172.16.0.0:80

    Here, protocol can be HTTP or HTTPS.

    This is a common URL that can be used for the endpoints that use the same host and port. A common URL is used because the authentication and data connection properties will be common for all endpoints.

    For example, you can use the base URL as www.abc.com/rest if you want to retrieve user attributes from the following REST endpoints:

    • www.abc.com/rest/getUserDepartmentInfo

    • www.abc.com/rest/getUserInfo

    You can add getUserDepartmentInfo and getUserInfo in Resource/API Path in the attribute source page. The attribute source page is used for retrieving attributes that are specific to each web service endpoint.

    Trusted Root

    Select one of the following options:

    • Verify from IDP trust store: Select this option if Identity Server must verify the SSL certificate of the web service.

      To import the trusted root from a specific web service, click Manage Web Service Trust Store.

      The trusted certificate of the server will be imported to the Identity Server trust store. Update the Identity Server each time.

    • Do not verify: Select this option if you do not require Identity Server to verify the SSL certificate of the web server.

    Connection Timeout

    Specify the duration until which Access Manager must try connecting to the REST web server in milliseconds. The default value is 15000 milliseconds. If the host is not reachable, clicking Test will give the timeout error after the specified duration.

    Authentication Type

    Select the type of authentication that will be required for connecting to the required web service.

    If you select Basic Auth, the Authorization header with the specified username and password gets added automatically to the request header, which is used for retrieving data from a REST endpoint.

    This ensures that the Authorization header gets added under the request header in the attribute source page.

    Credentials

    This field is displayed only when you select Authentication Type as Basic Auth.

    You can select any one of the following options:

    Admin: Specify the username and password for accessing the REST endpoints. Select this option if the REST web server requires a common credential to access all endpoints.

    Custom: Specify required LDAP attribute of users for accessing the REST endpoints. Use this option if the access to REST web server endpoints require specific user credentials.

    You must specify the credentials that authorizes a user to retrieve the information from the REST web server.

  7. To test the data source connection after specifying the details, click Test under Test Connectivity.

    You can also view the error logs at the following location:

    /opt/novell/nam/logs/adminconsole/tomcat/catalina.out

    NOTE:For a REST web service, clicking Test checks the connection to the web service irrespective of the endpoint's resource path and credentials. It checks the connection based on the IP address and port.

Editing a Data Source

  1. Click Devices > Identity Server > Shared Settings > Data Sources.

  2. Click the data source you want to modify.

  3. On the Edit Data Source page, modify the details as required.

    NOTE:If you change the IP address of the LDAP or REST web service data source, then, you must import the trusted root of the updated server to the Identity Server trust store.

    For more information about the fields on this page, see Creating a Data Source.

  4. Click OK.

  5. Update Identity Server.

IMPORTANT:You must update Identity Server when you edit properties of a data source that is in use by an attribute source and the attribute source in turn, being used by the virtual attribute.

Managing an Attribute Source

You can create, edit, or delete an attribute source.

NOTE:You cannot delete an attribute source that is being used by a virtual attribute.

This section discusses the following topics:

Creating an Attribute Source

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Attribute Source.

  2. Click + to add an attribute source.

  3. Specify a name and description for the attribute source.

  4. Select the data source.

  5. Specify the following details in Step 1: Provide input parameters:

    Field

    Description

    Name

    The default value is %P1% or {P1} based on the selection of data source.

    Specify the same name in Query or in fields that use the value of the attribute.

    Parameter Value

    Select an attribute from the list.

    Show / Add Test Values?

    Click this to display the test value, and specify a value in Test value.

    This value is used later when testing the query string or the web service.

    For REST web service, the input parameters can be used in creating resource API path, request headers, request body and the Advanced: Javascript response parsing functions. These can be tested using the test values. To use the input parameters, you must provide the parameter in the {<parameter name>} format, such as {P1}.

    When you click Test, the Test Results pane displays the status of the request and response based on the specified values.

    NOTE:For LDAP and database, the attribute source does not support multi-valued inputs. If you input multiple values, only one value is picked for the calculation.

    For REST web service, the attribute source supports multi-valued inputs for a parameter.

  6. (Conditional) For LDAP or database, specify the following details in Step 2: Provide query and output parameters:

    Field

    Description

    Query

    Specify an LDAP filter or a database query.

    The query must use the value specified in Step 1: Provide input parameters.

    Query Output Parameters

    Specify a name for the query output.

    To add multiple output parameters, click Add.

    • For an LDAP filter, specify the exact name of the attribute that you want to fetch.

    • For a database query, specify an alias for the attribute fetched. The order of the output parameters must match the sequence in which they are specified in the database query.

    Test

    Click to test the input values based on the filter and output parameters.

    For security reasons, you are prompted to enter the data source credentials. Test Result displays the status along with the test results. You can also view the error logs at the following location:

    /opt/novell/nam/logs/adminconsole/tomcat/catalina.out

    Example 2-1 Sample configuration

    See A Sample LDAP Scenario and A Sample Database Scenario.

  7. (Conditional) For REST web service, specify the following details in Step 2: Configure Request and Response:

    Field

    Description

    Base URL

    Auto-populated based on the details specified for the data source.

    Resource/API Path

    Specify the path of resource or API to be used along with the base URL to send a request to the REST web service.

    For example, if you require to fetch attributes from the www.abc.com/rest/getUserInfo endpoint and the base URL is www.abc.com/rest/, then specify Resource/API Path as getUserInfo.

    If REST web service requires the input parameters defined in Step 1: Provide input parameters, select Plain Text or Javascript and use the parameter within Resource/ API Path.

    Plain Text

    Select this when you need to add simple values, such as a constant value and unmodified input parameter values. You can use Plain Text in the following scenarios:

    • If the REST web server requires a constant value, such as user1, to be available in the resource/ API path, select Plain Text and specify Resource/ API Path as /getuserinfo/user1.

    • If the REST web server requires a user name to be available in Resource/ API Path for different users, use the input parameter {P1} with the givenName value to specify Resource/ API Path, such as /getuserinfo/{P1}.

    Javascript

    Select this when you need to add and modify complex values in Resource/ API Path. For example, if in the endpoint URL, REST web server requires the user’s name in lower case along with the last name in lowercase, you can specify the following in Resource/ API Path:

    function main({P1},{P2})
    var ret='/getuserinfo/'+ {P1}.toLowerCase()+"/"+{P2}.toLowerCase();
    return ret;
    }

    The return type of JavaScript can be string or array.

    NOTE:The input parameter can include multiple values, such as email (it can have values abc@example.com and abc@gmail.com). The multi-valued input parameter in the JavaScript main function are sent as a JavaScript array. If this attribute contains a single value for a specific user, this attribute is sent as a string to the JavaScript main function. So, ensure to check whether a parameter is sent as a string (single value) or as an array (multiple values) before processing it in the JavaScript main function.

    Method

    Select the request method that is accepted by the REST web server.

    GET and POST are the supported methods.

    Request Headers and Body

    Add request headers based on the REST endpoint configuration. By default, the Authorization header gets generated if you have selected Basic Auth during the creation of the REST web service Data source.

    You can add multiple headers for specific endpoints when configuring request headers. You can use the input parameter in the header value such as, {P1}.

    Specify the body message in plain text or JSON format. To specify the message using JavaScript, select Javascript.

    When you write a script, ensure that you request for the values that are either in string or in JSON format.

    Plain Text

    Select to include a constant input value or any input parameter value in the request body.The following example helps in understanding how to use the values in request body using plain text format:

    • If the body request should contain the constant values such as, john123 (userid), and abc (department) then you can specify Request > Body as {"userid": "john123", "department" : "abc"}

    • If the body request should contain some specific value that is variable and is not modified, then you can specify Request > Body as { "userid": {P1}, "department" : {P2}}

    Javascript

    Select to include a complex request body that requires modified input parameter values.The following example helps in understanding how to use the values in request body using the JavaScript format:

    function main({P1}, {P2}){
    var ret = '{ "userid":"'+ {P1} + '","department" : "'+ {P2}+'"}';
    return ret;
      }

    Response Parsing Function and Parameters

    To extract a specific response portion from the REST web server response, select the required response parsing function from the list.

    When a response is returned, you can use response parsing function to retrieve specific parameters that get mapped to the response parameters. This helps in retrieving the required values from the response. The Advanced: Javascript response parsing function can return single value (string, number, JSON) or multi-valued (array of strings, array of JSON) that get mapped to response parameters.

    Choose the required response parsing function along with its inputs under Response Parsing Function and Parameters. If you do not require to use the functions, you can choose No Response Parsing Function.

    For more information about each function, see Response Parsing Functions.

    Add

    Click to add parameter names to map to the values retrieved from the analyzed response.

    Response_As_Is is the default parameter that includes the complete response as it is received from the web server. You cannot delete Response_As_Is.

    • Sample JSON Response:

      {
      attribute1: "abc"
      attribute2: "pqr"
      }

      You get Response_As_Is under Response Parameters and you can specify attribute1 and attribute2 under Response Parameters. This maps the Response Parameters to the attribute values in the JSON response. Hence, attribute1 is mapped to abc and attribute2 is mapped to pqr.

    • Sample Array Response:

      result[0]
      result[1]

      You get Response_As_Is under Response Parameters and you can specify param1 and param2 under Response Parameters. This maps the Response Parameters to the attribute values in the array response. Hence, param1 is mapped to result[0] and param2 is mapped to result[1].

      For more information about mapping the parameters with the required attribute, see Retrieving Attributes from a REST Web Service.

    Example 2-2 Sample configuration

    See A Sample REST Service Scenario.

  8. To test this configuration:

    1. In Step 1: Provide input parameters, select Show / Add Test Values?, and provide a test value that is available as an attribute in the REST web server endpoint.

    2. In Step 2: Configure Request and Response, click Test. Specify the credentials that is defined while creating the data source. (See Creating a Data Source)

      Test results display the status for request and response. You can view the request URL, Headers, and Body under Request and view response parameters and headers under Response. The value of the parameters as retrieved from the response parsing function gets displayed in the test result window.

      The test result window displays the error message when the test result fails. For more information about the error you can check the logs at the following location:

      /opt/novell/nam/logs/adminconsole/tomcat/catalina.out

A Sample LDAP Scenario

You want to fetch an email address from an external LDAP directory for which a user’s LDAP attribute (from the external LDAP directory) UID matches with the local LDAP attribute cn.

To achieve this, perform the following steps:

  1. In Step 1: Provide input parameters, select LDAP attribute: cn as a parameter value. Add input parameter %P1% and map it to the LDAP attribute.

  2. In Step 2: Provide filter and output parameters:

    1. Specify (&(objectclass=*)(uid=%P1%)).

    2. Specify the filter output name as email. email is the alias name given for the column email.

  3. Test this configuration.

    1. In Step 1: Provide input parameters, select Show / Add Test Values? and provide the test value as admin.

    2. In Step 2: Provide filter and output parameters: Click Test. Enter the data source credentials.

The test result returns the email address stored in the directory: admin123@example.com.

A Sample Database Scenario

You want to fetch an email address from the database for which a user’s name matches with the local LDAP attribute cn.

To achieve this, perform the following steps:

  1. In Step 1: Provide input parameters, select LDAP attribute: cn as the parameter value.

  2. In Step 2: Provide query and output parameters:

    1. Specify select email from Emp where name = '%P1%' (email and name are the column name and Emp is the table name)

    2. Specify the filter output name as mail (mail is the alias name given for the column email).

  3. Test this configuration.

    1. In Step 1: Provide input parameters, select Show / Add Test Values?, and provide a test value that represents a record in the column of the table.

    2. In Step 2: Provide query and output parameters: Click Test. Specify the data source credentials.

The test results return the email address stored in the database: admin123@example.com.

A Sample REST Service Scenario

You have a web service that returns the roles of a user and you require to retrieve the designation of the user from the response received.

The endpoint of the REST web service: https://10.10.10.1:8543/rest/catalog/user1/roles/role

Base URL: https://10.10.10.1:8543/rest/catalog/

Request body:

"roles": [
    {
      "id": "cn=user1,cn=system,cn=usrapplication,ou=abc,ou=example,o=com"
    }
  ]
}

Response from REST web server (Response_As_Is):

{
    "roles": [
    {
      "id": "cn=user1,cn=system,cn=usrapplication,ou=abc,ou=example,o=com",
      "name": "user1",
      "designation": "Provisioning Administrator",
    "department": "Engineering",
      "level": 20,
      "subContainer": "system",
      "status": 50
    }
  ]
}

To retrieve the designation of user1 and map to Response Parameter, perform the following steps:

The response parameter mapped to the designation attribute value is used in virtual attribute.

  1. In Step1: Provide input parameters, specify {P1} with the givenName value.

    This input parameter is required because web server requires the user’s cn information in the request.

  2. In Step 2: Configure Request and Response:

    1. Select Plain Text and specify Resource/ API Path as {P1}/roles/role.

      Base URL is auto-populated from the value specified in the Data Source page, https://10.10.10.1:8543/rest/catalog/.

    2. Select Method as Post.

      In this scenario, the REST web service uses the POST method.

    3. In the Headers tab, Authorization is auto-populated. This header is retrieved from the REST Data Source page.

    4. Select Plain Text and specify the request body message:

      {
         "roles": 
        {"id":"cn={P1},cn=system,cn=usrapplication,ou=abc,ou=example,o=com"}
         ]
        }
    5. Select JSON Parse with Match Conditions.

    6. Specify the following Inputs:

      JSON Array Parse String: roles

      Match Conditions:

      Name: name

      Value: user1

  3. Test this configuration.

    1. In Step 2: Configure Request and Response, click Test. Specify the data source credentials.

      The Response_As_Is parameter is added by default.

    2. Click the edit icon next to the Response_As_Is parameter to view the complete response.

      To map designation attribute value to an output parameter, you must add designation as output parameter under Response Parameters.

      When the condition (name as user1) finds a match in the response, the designation value is retrieved and gets mapped to the designation parameter.

For information about retrieving response parameters, see Retrieving Attributes from a REST Web Service.

Editing an Attribute Source

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Attribute Source.

  2. Click the attribute source you want to modify.

  3. On the Edit Attribute Source page, modify the details as required.

    For more information about the fields on this page, see Creating an Attribute Source.

  4. Click OK. Update Identity Server.

IMPORTANT:If the attribute source is being used by a virtual attribute, you need to update Identity Server every time you edit the properties of an attribute source.

Managing a Virtual Attribute

You can create, edit, or delete a virtual attribute.

NOTE:You cannot delete a virtual attribute that is being used by an attribute set. Before deleting a virtual attribute, ensure that it is not being used by a policy.

This section discusses the following topics:

Creating a Virtual Attribute

You can create a virtual attribute from an attribute source and from an external data source.

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Virtual Attribute.

  2. Click + to create a virtual attribute.

  3. Specify a name and description for the virtual attribute.

  4. Click Step 1: Provide input > parameters and specify the following details:

    Field

    Description

    Name

    Specify a name for the attribute. If you use advanced JavaScript option, specify the same name in Advanced JavaScript. The default value is P1.

    Parameter Value

    Select an attribute from the list. To specify additional values, click +.

    NOTE:If an attribute source returns a null or an empty value, the corresponding input parameter takes an empty string value.

    Show / Add Test Values?

    Click to display Test value. You can add, edit, and delete a test value.

  5. Click Step 2: Provide a modification function and specify the following details:

    • Select a function: Select a function. The corresponding JavaScript is displayed in Script. Expand the script to view. You can further customize these scripts and use them in Advanced JavaScript.

      The following table lists the pre-defined JavaScript functions with examples:

      Function

      Description

      Example: Pre-Defined Functions

      To UpperCase

      Converts the input value to upper case.This function works on arrays and single-valued input. It uses the toUpperCase() JavaScript function.

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=alice, then the result displays ALICE.

      To LowerCase

      Converts the input value to lower case.This function works on arrays and single-valued input. It uses the toLowerCase() JavaScript function.

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=ALICE, then the result displays alice.

      Remove Substring

      Removes a substring from all instances of the input value. This function does not remove a substring from the global option.This function works on arrays and single-valued input. It uses the following JavaScript function: split() and join()

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=a@microfocus.com

      Remove=@microfocus, then the result is a.com.

      Find and Replace

      Finds and replaces a string from all instances of the input value.

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=abcde

      Find=e

      Replace=a, then the result displays abcda

      Regex Replace

      Finds and replaces a substring from all instances of the input value by using a regular expression.

      For example, to search /, you must escape it first using \. Use the following syntax: /\//

      This function works on arrays and single-valued input. It uses the following JavaScript functions: replace()

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=bob@novell.com

      Find=@novell.com

      Replace=@microfocus.com

      The result displays: bob@microfocus.com

      Find Subset by Regex

      Use this function if an input is multi-valued and you want a subset of values from it, satisfying a particular condition by using a regular expression.This function works on arrays and single-valued input. It uses the following JavaScript function: replace()

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If

      P1='’a@novell.com, b@novell.com,c @microfocus.com, d@microfocushr.com”

      regex= /microfocus/

      Then, the result displays:

      c@microfocus.com, d@microfocushr.com

      Concatenate Values in a Parameter

      Concatenates multiple values of a multi-valued input. You must add a separator between the values that you want to concatenate

      Works only on one input parameter that is selected in Step 1: Provide input parameters

      If P1=abc, def

      Separator=+

      Then, the result displays:

      abc+ def

      Concatenate Multiple Parameters

      Concatenates multiple input parameter values, where each input parameter can be multi-valued input. You must add a separator between the values that you want to concatenate

      If P1=abc, def

      and P2=123, 456

      Parameter Separator=+

      Multi value Separator=:

      Then, the result displays abc:def+123:456

      Advanced JavaScript

      Specify a customized JavaScript In this field. You need to create a JavaScript function with name “main” and specify the code in it. You can write your custom code or you can also copy the existing pre-defined code.You can also call multiple functions in the “main” function.

      See Sample JavaScripts with Examples.

      No Modification

      Use this function if you do not require any modification to the input parameters.

       

      IMPORTANT:

      • After JavaScript processing, if the output is a null value, the value of the virtual attribute is empty.

      • The pre-defined function can handle both single-valued and multi-valued inputs. If the input is multi-valued, the pre-defined function is applied on each values.

      Advanced JavaScript:

      Sample JavaScript:

      function main(P1, P2)
           {
                //some logic
                //you can call yourFunction(name) and use its return value
                return some value;
           }
           function yourFunction(name)
           {
                //some code
               //return some value;
           }

      For advanced JavaScript, the input parameter name in the main function of the JavaScript must match the input parameter name specified in Step 1: Provide input parameters. The return value can be a single value or an array.

      When the input is multi-valued, it is sent as an array to the main function.

      When Identity Server computes the value of a virtual attribute, it calls a function named main that is available in the script provided for it. The value (single value or array) returned by main is the value of the virtual attribute.

      For example: Consider a scenario where P1 contains bmw and nissan, you can use the JavaScript instanceof function to check if the input is single-valued or multi-valued. If it is multi-valued, then JavaScript iterates over the values P1=['bmw', 'nissan']

      function main (P1){
        if( P1 instanceof Array) {
          var a =P1[0]    //will assign 'bmw' value to variable a
          //do something
        }
      else{
       // if the P1 is single value not a array
      //do something
      }
      }

      The following code checks if an input parameter is empty, contains a value, or undefined:

      function main(P1){
        if(hasNoValue(P1))
          // do something
             return something;        
      }
      function hasNoValue(P1){
         if(P1 == null || (typeof P1 == 'undefined') || P1.trim().length == 0)
              return true;
         else 
              return false;
      }
    • Base64 Encode: (Conditional) Select this if you want to encode the modified attribute with Base64.

    • Test: Click this to test the input values based on the modification function. To test multi-valued inputs, click the + icon.

      For example, if an attribute mail has two values: abc@example.com and def@example.com, click the + icon twice. In each field, add the values separately.

      The test result displays the status with the test results. You can view the error logs at the following location:

      /opt/novell/nam/logs/adminconsole/tomcat/catalina.out

  6. Click OK and update Identity Server.

Editing a Virtual Attribute

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes.

  2. Click the virtual attribute you want to modify.

  3. On the Edit Virtual Attribute page, modify the details as required.

    For more information about the fields on this page, see Creating a Virtual Attribute.

  4. Click OK and update Identity Server.

IMPORTANT:You must update Identity Server each time you edit the properties of a virtual attribute.

Retrieving Attributes from a REST Web Service

This section illustrates examples for the following tasks:

  • Sending requests and retrieving responses from a REST web service

  • Using Response parsing functions

  • Using test values

Example for Using Input Parameter

You can use the input parameter in the JavaScript format in the request body.

In this example, the endpoint is https://abc.example.com:8543/users/rest/asset/roles/user. This endpoint uses the POST method for a HTTP request and the following body content:

{
   "users": [
       {"id":"cn= user1,cn=system,cn=userapplication,cn=app1,ou=example,o=com"}
   ]
}

To change the body content to JavaScript and provide cn from defined input parameters, perform the following steps:

  1. In Step1: Provide input parameters, specify {P1} as input parameter with parameter value cn.

    Add the test values for {P1} as user and system.

  2. In step 2: Configure Request and Response, change the request body message as follows:

    function main({P1}) {
    var cnValues = "cn=" + {P1}[0] + ",cn=" + {P1}[1]+ ",cn=userapplication,cn=app1,ou=example,o=com";
    var json = {
                    "users": [
                      {"id":cnValues}
                    ]
                    };
    return json;
    }

You can provide multiple test values to a parameter {P1} and use the values as array in the JavaScript function for Resource/ API Path and Body.

NOTE:If {P1} has only one input value, Access Manager interprets {P1} in JavaScript as a string and not as an array. Hence, for a single input value use {P1} instead of using {P1}[0].

If multiple values are available for {P1}, JavaScript returns all elements that are separated by a comma (,). For example, test1,test2. Whereas, {P1} in plain text returns only the first value. For example, test1.

Response Parsing Functions

When a REST web service receives a request, it returns a response. Access Manager adds the response body as the Response_As_Is parameter under Response Parameters. This parameter gets added by default. This function is used to get the specific data from a response. Most of the REST web services return responses in the JSON format. The response can be sent in any other format, such as xml and plain text. Access Manager includes the response parsing functions for JSON and XML. For any response that uses other formats, use the advanced JavaScript option.

You can add test values and click Test to test the result of the request.

The following example explains the response parsing functions:

Sample response returned from REST endpoint (Response_As_Is):

The REST web server returns the data of all students in an array of JSON format as mentioned in the following sample response:

{
  "students": [
    {
      "name": "xyz",
      "id": 1234,
      "subjects": [
        "English", "French"
      ],
      "department": "dept1",
      "branch": "IND"
    },
    {
      "name": "abc",
      "id": 124,
      "subjects": [
        "French"
      ],
      "department": "dept2",
      "branch": "IND"
    },

     { "name": "pqr",
      "id": 223,
      "subjects": [
        "Spanish"    
    ],
      "department": "Dept1",
      "branch": "IND"
    }]
}

This sample response is used as an example for JSON Parse, JSON Parse with Match Conditions, JSON Parse with Match Regex, and Advanced: Javascript.

The following is the list of functions:

  • JSON Parse: Parse the data with JSON Parse() to retrieve the data from JSON. This modification function uses the JavaScript’s JSON.Parse function. On selecting this response parsing function, you must specify JSON Parse String.

    Use the following inputs to retrieve specific attributes. You can provide the JSON Parse String value with standard JavaScript’s JSON.Parse function.

    JSON Parse String (input value)

    Scenario

    Response Parameter

    Test Result

    students[0].name

    The value of the name attribute is retrieved from the first JSON in the response. This value must be mapped to param1.

    param1

    param1=xyz

    The output is xyz as the value of the name attribute is xyz in the first array of JSON. The specified Response Parameter is param1, so the test result displays it as the parameter in response.

    students[1].name

    The value of the name attribute is retrieved from the second JSON in the response. This value must be mapped to name.

    name

    name=abc

    Here, the output is abc because the value of the name attribute is abc in the second array of JSON. The specified Response Parameter is name, so the test result displays it as the parameter in response.

    students[0].subjects[0]

    In this scenario, we are retrieving the first value of the subjects attribute from the first JSON of the response.

    param1

    param1=English

    Here, the output is English because the first value of the subjects attribute in the first array of JSON is English. The value for the subjects attribute is in an array format, so specifying subjects[0] in JSON Parsing String retrieves the first value in the array.

    students[0].subjects[1]

    The second value of the subjects attribute is retrieved from the first JSON of the response. This value must map to param1.

    param1

    param1=French

    The output for param1 is French as it is the second value of the subjects attribute in the first array of JSON. The value for the subjects attribute is in an array format, so specifying subjects[1] in JSON Parsing String retrieves the second value in the array.

    students[0]

    The values of students is retrieved from the first JSON of the response. These values must map with name, id and param1 in the same order.

    • name

    • id

    • param1

    • name=xyz

    • id=1234

    • param1=<no value gets displayed>

    The output is based on the number of values available for the students attribute. In the first array of JSON, only two values are available for students. The third parameter param1 is not mapped to any value.

    You can change the order of Response Parameter by using up and down arrow. The values are mapped based on the order specified for Response Parameter. For example, if the order of Response Parameter is as follows:

    • name

    • param1

    • id

    The output in the Results window displays:

    • name=xyz

    • param1=<no value gets displayed>

    • id=1234

  • JSON Parse with Match Conditions: This function finds an array from the response and then apply match conditions on the array elements to find the attribute that matches all the conditions. The following table includes the sample input value and its result when the data of a student whose department is dept1 is retrieved:

    Scenario: The value of students attribute that includes the attribute name department with value dept1 is retrieved.

    JSON Array Parse String (input value)

    Response Parameter

    Test Result

    students

    Match Conditions

    Name: department

    Value: dept1

    • name

    • id

    • param1

    • name=xyz

    • id=1234

    • param1=<no value gets displayed>

    When the condition is applied on the students JSON of array, the name parameter matches with name attribute of the response and the id parameter matches with the id attribute of the response. However, no param1 attribute is available in the response. Therefore, no value gets mapped to param1.

  • JSON parse with Match Regex: This is the same as JSON Parse with Match Conditions except that you can specify regex in the match condition. The following are examples of using regex:

    Scenario: Attribute values is retrieved from the students JSON of array that includes the attribute name as department and the value as dept1. The value dept1 is case-insensitive.

    JSON Array Parse String (input value)

    Response Parameter

    Test Result

    students

    Match Regex:

    Name: department

    Regex: /dept1/i

    • name

    • id

    • name={ "name": "xyz", "id": 1234, "subjects": [ "English", "French" ], "department": "dept1", "branch": "IND" }

    • id={ "name": "pqr", "id": 223, "subjects": [ "Spanish" ], "department": "Dept1", "branch": "IND" }

    The full JSON response is displayed for name and id as the specified regex condition is true for both dept1 and Dept1. As two matches are available for the specified condition, the parameters are mapped to two separate JSONs.

    Scenario: Attribute values of the attributes are retrieved from the students JSON of array that includes the attribute name as department and the value must be only dept1.

    JSON Array Parse String (input value)

    Response Parameters

    Test Result

    Match Regex:

    Name: department

    Regex: /dept1/

    • name

    • id

    • name=xyz

    • id=1234

    The exact match for both response parameters are displayed as one match is available for name and one match for id in the response that meets the mentioned condition.

  • Advanced JavaScript: Use this if you require any custom JavaScript to parse any kind of data returned by a web service. If a function is an array, the order of the parameters under Response Parameters is significant. However, the order is not significant for JSON as it maps to the same name. The following is an example script for parsing the response with Advanced: Javascript:

    Scenario: A JavaScript is written to retrieve the attribute and customize it based on the requirement. For adding the email parameter value, {P1} as input parameter is specified. A test value for {P1} as example is added.

    Script

    Response Parameters

    Test result

    function main(Response_As_Is, {P1}) {
      var jsonRes = JSON.parse(Response_As_Is);
      var p1Val = "";
      if({P1} instanceof Array) {
        var arrElem = {P1}[1];
        if(arrElem != undefined) {
           p1Val = arrElem;
        }
      } else {
         p1Val = {P1};
      }
      var arrResult = [];
      for(i = 0;i< jsonRes["students"].length -1; i ++) {
         var jsonTemp = {}; jsonTemp.id = jsonRes["students"][i]["id"];
         jsonTemp.mail = jsonRes["students"][i]["students"] + p1Val;
        arrResult.push(jsonTemp);
      }
      return arrResult;
    }

    Param1

    Param2

    Param1 : {
      "id": 123,
      "mail": " xyz@example.com"
    }
    Param2: {
      "id": 124,
      "mail": "abc@example.com"
    }

    The response from the REST web service is modified to return the array of students JSON that contains id and mail. The mail attribute is modified with the input parameter values. In this scenario, the result of the JavaScript is an array of JSONs. Hence, the response parameters param1 and param2 are mapped with each JSON (in the same order).

    You can change the order of Response Parameters by using up and down arrow. The values are mapped based on the order you specify. For example, the order of Response Parameters is as follows:

    • param2

    • param1

    The output in the Results window displays:

    param2 : {"id": 1234, "mail": "  xyz@example.com"
    }
    param1: {id": 124,"mail": "abc@example.com"
    }
  • XML Parse with XPath: You can use this if the web service response is in the form of XML, and you require to provide the XPath to extract the attribute from the xml based on the standard XPath format.

    Sample Response in xml format(Response_As_Is): The following is a sample response that is sent by a REST web service:

    <bookstore>
    <book>
    <title lang="en">
    Harry Potter
    </title>
    <price>
    29.99
    </price>
    </book>
    <book>
    <title lang="sp">
    Learning XML
    </title>
    <price>
    40
    </price>
    </book>
    <book>
    <title lang="dt">
    ABCD
    </title>
    <price>
    100
    </price>
    </book>
    </bookstore>

    XPath

    Scenario

    Response Parameter

    Test Result

    /bookstore/book/title/text()

    All values are retrieved from title nodes in the xml response.

    test

    test=[Harry Potter, Learning XML, ABCD]

    /bookstore/book[1]/title/text()

    The value is retrieved from title nodes within the first book node in the xml response.

    test

    test=Harry Potter

    /bookstore/book[1]/title

    The complete title node is retrieved within the first book node in the xml response.

    test

    <title lang="en">
    Harry Potter
    </title>

Response Parameters: When you select a response parsing function, you require to specify an output parameter under Response Parameters to get the required parameter mapped to the output parameter. You can use the parameter name specified under Response Parameters while configuring virtual attributes.

Sample JavaScripts with Examples

The following section provides sample JavaScripts with examples. These are used in the Virtual Attributes section.

Example 1:

Consider a scenario where a service provider wants to append PID with an attribute partnerId. For example: PID: P1.

To achieve this, fetch a user’s partnerId by using their existing “givenName” LDAP attribute (available from the logged in user store) from the external LDAP repository. Now, add a string “PID:” to it. Later, send the value in web servers through the Identity injection policy.

Solution: The solution is as follow:

Creating a Data Source:

  1. Configure an LDAP data source with name “dsLdap”. Specify the connection properties. Test the connection.

  2. Import the secure LDAP certificate to Identity Server trust store using the create Data Source screen.

  3. Click Update All to update Identity Servers.

Creating an Attribute Source:

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Attribute Source. Create an attribute source with name “dsLdapAttrSrc”.

  2. Select data source name “dsLdap”.

  3. Add input parameter %P1%. Map it to the LDAP attribute: givenName.

  4. Add a Filter: name=%P1%.

  5. Add output parameter: partnerID

  6. Test Filter: Test the input values.

Creating a Virtual Attribute:

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Virtual Attribute. Create a virtual attribute with name “partnerID”.

  2. Add input parameter P1. Map it to dsLdapAttrSrc:partnerID (the attribute source that you created in Step 1 of the creating an Attribute Source section).

  3. In Step 2: Provide query and output parameters, specify the following script:

    function main(P1){
       return "PID:"+P1;
    }
  4. Test the script. The results return: PID: P1. For example, if partnerID=part123, then, the test result is PID:part123.

  5. Update Identity Server.

  6. Use it in the Identity injection policy.

Example 2:

Consider a scenario where the authenticated user, named Carlos, is a manager and has administrator rights to a protected human resource application. When Carlos accesses this application, his roles must be passed to the application.

In this scenario, Carlos has a local LDAP attribute isManager and has roles of a recruiter and an employee. He also has a local LDAP attribute groupmembership, which contains the string admins (for example, adminsRecruitmentDep, adminsPoliciesDep).

Solution: Create a virtual attribute, App1Admin.

  1. In Step1: Provide input parameters, select the following input parameters:

    • P1: is mapped to LDAP attribute isManager

    • P2: is mapped to LDAP attribute groupmembership

    • P3: is mapped to LDAP attribute role value

  2. Use the following code in Step 2: Provide a modification function > Advanced Javascript:

    function main(P1, P2, P3){
         if(P1 == 'true' && (/admins/i.test(P2) == true)){
           return P3;
         }else{
           return 'NA';
         }  
    }
  3. To test JavaScript, click + and add multiple test values. Specify the following test values:

    • P1: true

    • P2: adminsRecruitmentDep

    • P3: recruiter,employee

    Output: The output is a multi-valued virtual attribute recruiter,employee.

In the function, /admins/i.test(P2) == true, /admins/i is a regular expression and test is a JavaScript in-built function. This function tests the regular expression in the string passed as the input parameter. The function returns true if the string contains the required pattern.

Example 3:

Consider a scenario where an Access Manager user wants to access Amazon Web Services (AWS). AWS has multiple roles and each AWS role can have various access rights or policies assigned to it. Based on the level of access, you can access authorized Amazon services. This information about roles must be sent dynamically by Access Manager to AWS to provide single sign-on to the Access Manager user.

For more information about AWS configuration, see Integrating Amazon Web Services with Access Manager.

In this scenario, you have a constant value created using <Role ARN, Trusted SAML Provider ARN> mapped to Remote AWS attribute Role (this value is the AWS format).

Suppose you have configured the admin and finance roles in AWS. The following are role ARNs:

  • For admin: arn:aws:iam::638116851885:role/admin

  • For finance: arn:aws:iam::638116851885:role/finance

For admin role, send the following: arn:aws:iam::638116851885:role/admin,arn:aws:iam::638116851885:saml-provider/NAMIDP

For finance role, send the following: arn:aws:iam::638116851885:role/finance,arn:aws:iam::638116851885:saml-provider/NAMIDP

In this example, to dynamically generate the AWS role, use the LDAP attribute Department Name in the user store. For the admin user, the department name is admin. For the finance user, the department name is finance. To make department name available as an LDAP attribute, ensure that you enable personal profile. Click Identity Servers > Edit > Liberty > Web Service Provider.

Solution: Create a virtual attribute with the following information:

When the user logs in, the department name (finance) is fetched for the respective user and appended with the constant value of the role ARN. This value is then concatenated with the trusted SAML provider ARN in the following format: arn:aws:iam::638116851885:role/admin,arn:aws:iam::638116851885:saml-provider/NAMIDP

Map this virtual attribute with the AWS Remote Attribute role.

  1. In Step1: Provide input parameters, select P1 parameter value as Department Name (Personal Profile).

  2. Use the following code in Step 2: Provide a modification function > Advanced Javascript:

    function main(P1){
       var role_arn='arn:aws:iam::638116851885:role/'
       var provider_arn=',arn:aws:iam::638116851885:saml-provider/MyIDP_184-142';
       var aws_role;
       aws_role = role_arn+P1+provider_arn;
       return aws_role;
    }
  3. To test JavaScript, click the + and add multiple test values. Specify the test value of P1: finance.

    Output: arn:aws:iam::638116851885:role/finance,arn:aws:iam::638116851885:saml-provider/NAMIDP.

Example 4:

You want to send the groups associated with the user to a service provider named cloudsp. However, you want to send only the groups relevant to that service, and not the complete group DN. Check for a function that checks if the group cn starts with “cloudsp”. If available, send it to the group cn.

In this scenario, the cn of the groups relevant to cloudsp start with “cloudsp”. For example, "cn=cloudspa,ou=group,o=mycompany". So, when a cloudsp user authenticates at Identity Server, you need to extract all cn values from the local LDAP attribute groupMembership and filter only those names starting with cloudsp and send it in assertion to cloudsp.

Solution:

  1. In Step1: Provide input parameters, select P1 as an attribute which has the groups.

  2. Use the following code in Step 2: Provide a modification function > Advanced Javascript:

    function main( P1 ){
          return mapGroups(P1);
    }
    
    function mapGroups(attribute){
        var result = [];
          if(attribute instanceof Array){
            var j =0;
            for(var i=0; i<attribute.length; i++){
                var grp = checkGroup(attribute[i]);
                if( grp != 'NA')
                   result[j++] = grp;
                 }
        }else{
                var grp = checkGroup(attribute);
            if( grp != 'NA')
                      result[0] = grp;
        }
          return result;
    }
    
    function checkGroup(group){
        if(/^cn=cloudsp.*,/.test(group) == true){
            var startindex = 3;// it starts with cn
            var endindex = group.indexOf(",");
            return group.substring( startindex, endindex);
         }else
            return 'NA';
    }
  3. To test JavaScript, click the + and add multiple test values. Specify the test values:

    cn=cloudspgroupa,ou=group,o=mycompany cn=cloudspgroupb,ou=group,o=mycompany cn=cloudspgroupk,ou=group,o=mycompany

    cn=testgroupa,ou=group,o=mycompany

    Output:

    cloudspgroupa
    cloudspgroupb
    cloudspgroupk

Explanation:

The JavaScript in-built string function substring is used to extract the cn value from the group./^cn=cloudsp.*,/.test(group) is a regular expression which matches a string that starts with cloudsp. It has 0 or more characters followed by a comma (,).

Example 5:

(Utility Function Reuse) Consider a scenario where the Identity Server roles are in the format companyX:rolename. A service provider abc wants the roles in the rolename format and in upper case.

To achieve this, remove 'companyX:' from each role and convert each of them into upper case for sending them to the protected web server. Each role is specified as companyX:rolename.

For example, companyX:admin, companyX:guest.

Solution:

  1. In Step 1: Provide input parameters, select P1: All Roles.

  2. Use the following code in the Step 2: Provide a modification function > Advanced Javascript:

    Copy the JavaScript from the following pre-defined functions: Remove Substring and To upperCase.

    Remove Substring function:

    function findReplace(attribute, findString, replaceString){
          var result;
        if(attribute instanceof Array){
                 result = [];
             for(var i=0; i<attribute.length; i++){
                       result[i] =attribute[i].split(findString).join(replaceString);
             }
          }else{
             result = attribute.split(findString).join(replaceString);
          }
        return result;
    }

    To upperCase function:

    function convertToUpperCase (attribute){
          var result ;
        if(attribute instanceof Array){
                result = [];
            for(var i=0; i<attribute.length; i++)
                      result[i] = attribute[i].toUpperCase();
        }else{
                  result = attribute.toUpperCase();
        }
        return result;
    }

    Now, customize the code. In Substring to remove for findReplace (), specify companyX:

    function main(P1){
        return convertToUpperCase(findReplace (P1, 'CompanyX:'));
    }
    
    function findReplace(attribute, findString, replaceString){
        var result ;
          if(attribute instanceof Array){
            result = [];
                for(var i=0; i<attribute.length; i++){
                result[i] =attribute[i].split(findString).join(replaceString);
                }
        }else{
                result = attribute.split(findString).join(replaceString);
        }
          return result;
    }
    
    function convertToUpperCase (attribute){
        var result;
          if(attribute instanceof Array){
            result = [];
                for(var i=0; i<attribute.length; i++)
                result[i] = attribute[i].toUpperCase();
            }else{
            result = attribute.toUpperCase();
          }
        return result;
    }
    
  3. To test JavaScript, add the test values in P1: 'companyX:admin', 'companyX:guest'.Output: ADMIN, GUEST.

Example 6:

Consider a scenario where you do not want to modify an attribute value that is retrieved from an external source. To send the same attribute value in the assertion to a federated provider or in a policies, perform the following steps:

  1. Click Devices > Identity Server > Shared Settings > Virtual Attributes > Virtual Attribute.

  2. In Step1: Provide input parameters, select P1, and map it to an attribute retrieved from an external source.

  3. In Step 2: Provide a modification function, select Advanced JavaScript, and specify the following script:

    function main(P1){
        return P1;
    }
  4. Test the script. The results returns the value of the attribute source specified as P1.

  5. Update Identity Server.

Troubleshooting User Attribute Retrieval and Transformation

For troubleshooting information, see Troubleshooting User Attribute Retrieval and Transformation.

User Attribute Retrieval and Transformation Limitations

  • For LDAP and database sources, the multi-valued input parameters are not supported in the attribute source. If you input a multi-valued parameter, only one value is picked for the calculation.

  • You cannot use the existing Identity server user stores directly as an attribute source. You must create a separate data source to use the user stores.

  • You cannot edit or store any attribute value permanently in the existing LDAP attributes, shared secret attributes, or external database by using virtual attributes.

  • SSL communication with SQL and Oracle databases that are used by virtual attributes (data sources) is not supported.