Sunday, March 4, 2012

OIM 11.1.1.5 Develop Connectors using ICF and SPI APIS.. Part 2

OIM 11.1.1.5 Develop Connectors using ICF and SPI APIS.. Part 2 Create connector class for the Flat File Connector by implementing the org.identityconnectors.framework.spi.Connector interface.

This class implements the CreateOp, DeleteOp, SearchOp and UpdateOp interfaces and thus supports all four operations. The FlatFileMetadata, FlatFileParser and FlatFileWriter classes are supporting classes.

package org.identityconnectors.flatfile;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.identityconnectors.flatfile.io.FlatFileIOFactory;
import org.identityconnectors.flatfile.io.FlatFileMetadata;
import org.identityconnectors.flatfile.io.FlatFileParser;
import org.identityconnectors.flatfile.io.FlatFileWriter;
import org.identityconnectors.framework.api.operations.GetApiOp;
import org.identityconnectors.framework.common.exceptions.AlreadyExistsException;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.ResultsHandler;
import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.SchemaBuilder;
import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator;
import org.identityconnectors.framework.spi.Configuration;
import org.identityconnectors.framework.spi.ConnectorClass;
import org.identityconnectors.framework.spi.PoolableConnector;
import org.identityconnectors.framework.spi.operations.CreateOp;
import org.identityconnectors.framework.spi.operations.DeleteOp;
import org.identityconnectors.framework.spi.operations.SchemaOp;
import org.identityconnectors.framework.spi.operations.SearchOp;
import org.identityconnectors.framework.spi.operations.UpdateOp;

/**
 * The main connector class
 */
@ConnectorClass(configurationClass = FlatFileConfiguration.class, displayNameKey = "FlatFile")
public class FlatFileConnector implements SchemaOp, CreateOp, DeleteOp,
        UpdateOp, SearchOp<Map<String, String>>, GetApiOp, PoolableConnector {

    private FlatFileConfiguration flatFileConfig;
    private FlatFileMetadata flatFileMetadata;
    private FlatFileParser flatFileParser;
    private FlatFileWriter flatFileWriter;
    private boolean alive = false;

    @Override
    public Configuration getConfiguration() {
        return this.flatFileConfig;
    }

    @Override
    public void init(Configuration config) {
        this.flatFileConfig = (FlatFileConfiguration) config;

        FlatFileIOFactory flatFileIOFactory =
             FlatFileIOFactory.getInstance(flatFileConfig);
        this.flatFileMetadata = flatFileIOFactory.getMetadataInstance();
        this.flatFileParser = flatFileIOFactory.getFileParserInstance();
        this.flatFileWriter = flatFileIOFactory.getFileWriterInstance();
        this.alive = true;
        System.out.println("init called: Initialization done");
    }

    @Override
    public void dispose() {
        this.alive = false;
    }

    @Override
    public Schema schema() {
        SchemaBuilder flatFileSchemaBldr = new SchemaBuilder(this.getClass());
        Set<AttributeInfo> attrInfos = new HashSet<AttributeInfo>();
        for (String fieldName : flatFileMetadata.getOrderedTextFieldNames()) {
            AttributeInfoBuilder attrBuilder = new AttributeInfoBuilder();
            attrBuilder.setName(fieldName);
            attrBuilder.setCreateable(true);
            attrBuilder.setUpdateable(true);
            attrInfos.add(attrBuilder.build());
        }
       
        // Supported class and attributes
        flatFileSchemaBldr.defineObjectClass
          (ObjectClass.ACCOUNT.getDisplayNameKey(),attrInfos);
        System.out.println("schema called: Built the schema properly");
        return flatFileSchemaBldr.build();
    }

    @Override
    public Uid create(ObjectClass arg0, Set<Attribute> attrs,
            OperationOptions ops) {

        System.out.println("Creating user account " + attrs);
        assertUserObjectClass(arg0);
        try {
            FlatFileUserAccount accountRecord = new FlatFileUserAccount(attrs);
            // Assert uid is there
            assertUidPresence(accountRecord);

            // Create the user
            this.flatFileWriter.addAccount(accountRecord);

            // Return uid
            String uniqueAttrField = this.flatFileConfig
                    .getUniqueAttributeName();
            String uniqueAttrVal = accountRecord
                    .getAttributeValue(uniqueAttrField);
            System.out.println("User " + uniqueAttrVal + " created");
           
            return new Uid(uniqueAttrVal);
        } catch (Exception ex) {

            // If account exists
            if (ex.getMessage().contains("exists"))
                throw new AlreadyExistsException(ex);

            // For all other causes
            System.out.println("Error in create " + ex.getMessage());
            throw ConnectorException.wrap(ex);
        }
    }

    @Override
    public void delete(ObjectClass arg0, Uid arg1, OperationOptions arg2) {
        final String uidVal = arg1.getUidValue();
        this.flatFileWriter.deleteAccount(uidVal);
        System.out.println("Account " + uidVal + " deleted");
    }

    @Override
    public Uid update(ObjectClass arg0, Uid arg1, Set<Attribute> arg2,
            OperationOptions arg3) {
        String accountIdentifier = arg1.getUidValue();
        // Fetch the account
        FlatFileUserAccount accountToBeUpdated = this.flatFileParser
                .getAccount(accountIdentifier);

        // Update
        accountToBeUpdated.updateAttributes(arg2);
        this.flatFileWriter
                .modifyAccount(accountIdentifier, accountToBeUpdated);
        System.out.println("Account " + accountIdentifier + " updated");

        // Return new uid
        String newAccountIdentifier = accountToBeUpdated
                .getAttributeValue(this.flatFileConfig.getUniqueAttributeName());
        return new Uid(newAccountIdentifier);
    }

    @Override
    public FilterTranslator<Map<String, String>> createFilterTranslator(
            ObjectClass arg0, OperationOptions arg1) {
        // TODO: Create a fine grained filter translator

        // Return a dummy object as its not applicable here.
        // All processing happens in the execute query
        return new AbstractFilterTranslator<Map<String, String>>() {
        };
    }

    @Override
    public ConnectorObject getObject(ObjectClass arg0, Uid uid,
            OperationOptions arg2) {
        // Return matching record
        String accountIdentifier = uid.getUidValue();
        FlatFileUserAccount userAcc = this.flatFileParser
                .getAccount(accountIdentifier);
        ConnectorObject userAccConnObject = convertToConnectorObject(userAcc);
        return userAccConnObject;
    }

    /*
     * (non-Javadoc)
     * This is the search implementation.
     * The Map passed as the query here, will map to all the records with
     * matching attributes.
     *
     * The record will be filtered if any of the matching attributes are not
     * found
     *
     * @see
     * org.identityconnectors.framework.spi.operations.SearchOp#executeQuery
     * (org.identityconnectors.framework.common.objects.ObjectClass,
     * java.lang.Object,
     * org.identityconnectors.framework.common.objects.ResultsHandler,
     * org.identityconnectors.framework.common.objects.OperationOptions)
     */
    @Override
    public void executeQuery(ObjectClass objectClass,
            Map<String, String> matchSet, ResultsHandler resultHandler,
            OperationOptions ops) {

    System.out.println("Inside executeQuery");
   
        // Iterate over the records and handle individually
        Iterator<FlatFileUserAccount> userAccountIterator = this.flatFileParser
                .getAccountIterator(matchSet);

        while (userAccountIterator.hasNext()) {
            FlatFileUserAccount userAcc = userAccountIterator.next();
            ConnectorObject userAccObject = convertToConnectorObject(userAcc);
            if (!resultHandler.handle(userAccObject)) {
                System.out.println("Not able to handle " + userAcc);
                break;
            }
        }
    }

    private void assertUserObjectClass(ObjectClass arg0) {
        if (!arg0.equals(ObjectClass.ACCOUNT))
            throw new UnsupportedOperationException(
                    "Only user account operations supported.");

    }

    private void assertUidPresence(FlatFileUserAccount accountRecord) {
        String uniqueAttrField = this.flatFileConfig.getUniqueAttributeName();
        String uniqueAttrVal = accountRecord.getAttributeValue(uniqueAttrField);

        if (uniqueAttrVal == null) {
            throw new IllegalArgumentException("Unique attribute not passed");
        }
    }

    private ConnectorObject convertToConnectorObject(FlatFileUserAccount userAcc) {
        ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
        // Add attributes
        List<String> attributeNames = this.flatFileMetadata
                .getOrderedTextFieldNames();
        for (String attributeName : attributeNames) {
            String attributeVal = userAcc.getAttributeValue(attributeName);
            userObjBuilder.addAttribute(attributeName, attributeVal);

            if (attributeName.equals(this.flatFileConfig
                    .getUniqueAttributeName())) {
                userObjBuilder.setUid(attributeVal);
                userObjBuilder.setName(attributeVal);
            }
        }
        return userObjBuilder.build();
    }

    @Override
    public void checkAlive() {
        if (!alive)
            throw new RuntimeException("Connection not alive");
    }

}

OIM 11.1.1.5 Develop Connectors using ICF and SPI APIS.. Part 1

OIM 11.1.1.5 Develop Connectors using ICF and SPI APIS: Part1:: Implement the configuration class for the Flat File Connector by extending the org.identityconnectors.framework.spi.AbstractConfiguration base class.

  • The implementation of this interface encapsulates the configuration of a connector. Configuration implementation includes all the necessary information of the target system, which is used by the Connector implementation to connect to the target system and perform various reconciliation and provisioning operations. 
  • The implementation should have a default Constructor with setters and getters defined for its properties. Every property declared may not be required but if a property is required, then it should be marked required using the annotation org.identityconnectors.framework.spi.ConfigurationProperty. Configuration implementation is a Java bean and all the instance variables (mandatory or not) do have default values. For example, a string userName is used to connect to the target system and this is a mandatory attribute. This has a default value of null. When userName is a mandatory attribute, ICF expects a value to be provided by Oracle Identity Manager. In other words, Oracle Identity Manager cannot miss out this parameter. If missed, then the connector throws ConfigurationException.
  • The implementation should check that all required properties are available and validated before passing itself to the Connector. The interface provides a validate method for this purpose. For example, there are three mandatory configuration parameters, such as the IP address of the target, the username to connect to the target, and the password for the user. The validate method implementation can check for non-NULL values and valid IP address by using regex.
package org.identityconnectors.flatfile;
import java.io.File;
import org.identityconnectors.flatfile.io.FlatFileIOFactory;
import org.identityconnectors.framework.common.exceptions.ConfigurationException;
import org.identityconnectors.framework.spi.AbstractConfiguration;
import org.identityconnectors.framework.spi.ConfigurationProperty;
/**
 * Class for storing the flat file configuration
 */
public class FlatFileConfiguration extends AbstractConfiguration {
/*
 * Storage file name
 */
private File storeFile;
/*
 * Delimeter used
 */
private String textFieldDelimeter;    
/*
 * Unique attribute field name
 */
private String uniqueAttributeName = "";
/*
 * Change attribute field name. Should be numeric
 */
private String changeLogAttributeName = "";

public File getStoreFile() {
return storeFile;
}

public String getTextFieldDelimeter() {
return textFieldDelimeter;
}

     public String getUniqueAttributeName() {
        return uniqueAttributeName;
    }

    public String getChangeLogAttributeName() {
        return changeLogAttributeName;
    }

    /**
     * Set the store file
     * @param storeFile
     */
    @ConfigurationProperty(order = 1, helpMessageKey = "USER_ACCOUNT_STORE_HELP",
            displayMessageKey = "USER_ACCOUNT_STORE_DISPLAY")
    public void setStoreFile(File storeFile) {
        this.storeFile = storeFile;
    }

    /**
     * Set the text field delimeter
     * @param textFieldDelimeter
     */
    @ConfigurationProperty(order = 2,
            helpMessageKey = "USER_STORE_TEXT_DELIM_HELP",
            displayMessageKey = "USER_STORE_TEXT_DELIM_DISPLAY")
    public void setTextFieldDelimeter(String textFieldDelimeter) {
        this.textFieldDelimeter = textFieldDelimeter;
    }

    /**
     * Set the field whose values will be considered as unique attributes
     * @param uniqueAttributeName
     */
    @ConfigurationProperty(order = 3, helpMessageKey = "UNIQUE_ATTR_HELP",
            displayMessageKey = "UNIQUE_ATTR_DISPLAY")
    public void setUniqueAttributeName(String uniqueAttributeName) {
        this.uniqueAttributeName = uniqueAttributeName;
    }

    /**
     * Set the field name where change number should be stored
     * @param changeLogAttributeName
     */
    @ConfigurationProperty(order = 3, helpMessageKey = "CHANGELOG_ATTR_HELP",
            displayMessageKey = "CHANGELOG_ATTR_DISPLAY")
    public void setChangeLogAttributeName(String changeLogAttributeName) {
        this.changeLogAttributeName = changeLogAttributeName;
    }  
    @Override
    public void validate() {
      
        // Validate if file exists and is usable
        boolean validFile = (this.storeFile.exists() &&
                this.storeFile.canRead() &&
                this.storeFile.canWrite() &&
                this.storeFile.isFile());
      
        if (!validFile)
            throw new ConfigurationException("User store file not valid");
      
        // Validate if there is a field on name of unique attribute field name      
        // Validate if there is a field on name of change attribute field name
        FlatFileIOFactory.getInstance(this);
        // Initialization does the validation
    }
  
  
}

Thursday, March 1, 2012

WebLogic 10.3.5 SSL Handshake

As a function of the SSL handshake, WebLogic Server compares the common name in the SubjectDN in the SSL server’s digital certificate with the host name of the SSL server used to initiate the SSL connection. If these names do not match, the SSL connection is dropped. The SSL client is the actual party that drops the SSL connection if the names do not match.

The following Java Program can be run from the  $MW_HOME/common/bin directory to see if the SSL handshake is happening. Also, before running the Java Code, the commEnv.sh need to be run to setup the Java environment.
import java.net.*;
import java.io.*;

public class SSLTest {

    public SSLTest() {
        super();
    }

    public static void main(String[] args) throws Exception {
        
        URL verisign = new URL("https://someserver.net:999/someservice?wsdl");
        System.out.println("Opening URL: " + verisign.toString());

        BufferedReader in =
            new BufferedReader(new InputStreamReader(verisign.openStream()));

        String inputLine;
        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);

        in.close();
    }
}


Before running the Java Code, the following environment variables need to be set.
-Djavax.net.ssl.trustStorePassword=trustPassword 

-Dssl.debug=true 

-Dweblogic.StdoutDebugEnabled=true 

-Djavax.net.debug=ssl,handshake,verbose 

-Djavax.net.ssl.trustStore=C:\OSB\Middleware\wlserver_10.3\server\lib\mindtelligent-trust.jks 
-Djavax.net.ssl.keyStore=C:\OSB\Middleware\wlserver_10.3\server\lib\mindtelligent-identity.jks  


-Djavax.net.ssl.keyStorePassword=IdentityPassword

Tuesday, February 28, 2012

Weblogic 10.3.5 Configuring a PKI Credential Mapping Provider

Weblogic 10.3.5 Configuring a PKI Credential Mapping Provider

The PKI (Public Key Infrastructure) Credential Mapping provider included in WebLogic Server maps (a) a WebLogic Server subject (the initiator) and target resource (and an optional credential action) to (b) a key pair or public certificate that can be used by applications when accessing the targeted resource. The PKI Credential Mapping provider uses the subject and resource name to retrieve the corresponding credential from the keystore.

Configure the infrastructure for using key pair or certificate credential mappings:
  1. Configure a PKI Credential Mapping provider. A PKI Credential Mapping provider is not already configured in the default security realm (myrealm).  
  2. Configure keystores with appropriate keys and distribute the keystores on all machines in a WebLogic Server cluster. For information about setting up keystores, see the help for the Java keytool utility at http://java.sun.com/j2se/1.4.2/docs/tooldocs/solaris/keytool.html . 

To create a key pair or certificate based credential mapping for the WebLogic Credential Mapping provider:
  1. In the left pane, select Security Realms and click the name of the realm you are configuring (for example, myrealm)
  2. Select Credential Mappings > PKI. The PKI Credential Mappings table lists the PKI Credential Mappings configured in this security realm.
  3. Click New. The Create a New Security Credential Mapping page appears.
  4. Enter information about the remote resource to be accessed using this credential mapping. This information is used to identify the remote resource and can include one or more of the following:
    1. Protocol—The protocol to use to reach the remote resource.
    2. Remote Host—The host name of the remote resource.
    3. Remote Port—The port number of the remote resource.
    4. Path—If the remote resource is identified by a path, rather than a hostname and port.
    5. Method—The method on the remote resource this credential is used with.
    Click Next.
  5. On the Create a New Security Credential Map Entry page, select Key Pair or Certificate to indicate the type of credential you are mapping to.
  6. Enter the name of the principal that you are mapping from. This is the WebLogic username that will be the initiator when you want to access the remote resource using this credential mapping.
  7. Indicate whether the principal that you are mapping from is a user or a group.
  8. Optionally, specify a credential action.  
  9. Enter the alias used in the keystore to identify the credential.
  10. If this is a Key Pair credential, enter the password used to retrieve the credential from the keystore.
  11. Click Finish.

 






Monday, February 27, 2012

Weblogic 10.3.5: Steps for Using WLST

Weblogic 10.3.5: Steps for Using WLST

Setting Up Your Environment

To set up your environment for WLST:
  1. Install and configure the WebLogic Server software.
  2. Add WebLogic Server classes to the CLASSPATH environment variable and WL_HOME\server\bin to the PATH environment variable, where WL_HOME refers to the top-level installation directory for WebLogic Server.
  3. You can use a WL_HOME\server\bin\setWLSEnv script to set both variables.
    On Windows, a shortcut on the Start menu sets the environment variables and invokes WLST (ToolsArrow symbolWebLogic Scripting Tool).
     

Invoking WLST

To invoke WLST:
  1. If you will be connecting to a WebLogic Server instance through an SSL listen port on a server that is using the demonstration SSL keys and certificates, invoke WLST using the following command:
  2. java -Dweblogic.security.SSL.ignoreHostnameVerification=true -Dweblogic.security.TrustKeyStore=DemoTrust weblogic.WLST
    Otherwise, at a command prompt, enter one of the following commands:
    • java weblogic.WLST
    • java weblogic.WLST -loadProperties propertyFilename

Running WLST from Ant

The wlst Ant task is predefined in the version of Ant shipped with WebLogic Server and enables you to run WLST scripts from within your Ant build file.

Note: If you want to use the task with your own Ant installation, add the following task definition in your build file:

Note: <taskdef name="wlst" classname="weblogic.ant.taskdefs.management.WLSTTask" />
To run WLST from an Ant script:
  1. Set your environment in a command shell.
    • On Windows NT, execute the setWLSEnv.cmd command, located in the directory WL_HOME\server\bin, where WL_HOME is the top-level directory of your WebLogic Server installation.
    • On UNIX, execute the setWLSEnv.sh command, located in the directory WL_HOME/server/bin, where WL_HOME is the top-level directory of your WebLogic Server installation.
  2. Add a call to the wlst Ant task to execute WLST commands. For example:
  3. <target name="runwlst"> 
       <wlst fileName="./myscript.py" executeScriptBeforeFile="true"
        debug="false" failOnError="false"> 
         <script>
            connect('weblogic','weblogic','t3://localhost:7001') 
         </script>
       </wlst>
    </target>

Oracle SOA 11.1.1.5 Transferring Metadata using WLST

Transferring Metadata using WLST

To use WLST to transfer metadata:
  1. Export the metadata from the original partition using the exportMetadata command:
    exportMetadata(application='sampleApp', server='server1',
           toLocation='/tmp/myrepos/mypartition', docs='/**')
    
    This command exports a versioned stripe of the metadata documents from the metadata partition to a file system directory. Only customization classes declared in the cust-config element of adf-config.xml are exported. If there is no cust-config element declared in adf-config.xml, all customization classes are exported.
    To export all customizations, use the option restrictCustTo="%".
  2. If the production application is on a different system, copy the exported metadata to that system.
  3. Import the metadata to the other partition using the WLST importMetadata command:
    importMetadata(application='sampleApp', server='server1',
           fromLocation='/tmp/myrepos/mypartiton', docs='/**')
    
    The value of the fromLocation parameter must be on the same system that is running WLST or on a mapped network drive or directory mount. You cannot use direct network references such as \\mymachine\repositories\.
    Only customization classes declared in the cust-config element of adf-config.xml are imported. If there is no cust-config element declared in adf-config.xml, all customization classes are imported.
    To import all customizations, use the option restrictCustTo="%".

How IdP Groups Are Tied to Databricks Groups (Unity Catalog)

  🔗 How IdP Groups Are Tied to Databricks Groups (Unity Catalog) 🔑 Key Principle (Read This First) Databricks does NOT “map” IdP groups...