Archive for the ‘Security’ Category

Oh boy. it’s late and I’ve been working quite hard lately, both on the current day job and lately with my side project which is what I wanted to share with everyone here and now.
I’ve started writing some training course material about the CSSDK in all its glory in the hope that someone out there would take me up on the offer and sign up for a training session.
It’s early stages yet, although I’ve already written 5 sections out of what I think will be about 10. This means I’m half way there (Hurray!) and that means I need to start broadcasting this to the whole wide world and start generating some interest. An interesting point is Interwoven Autonomy HP (?) does not seem to cover it in any great detail.
Up until now, I have written (besides the training plan):
  • a succinct introduction,
  • a chapter on how to configure the IDE with the TeamSite jars and JavaDocs,
  • a chapter on the CSFactory and getting connected to teamsite (locally and via SOAP, if you please),
  • a chapter on the common package, the CSClient and other assorted bits
  • a chapter on users, groups and roles and operations.

Impressions to this date on the work has been fairly positive. I’ve enjoyed writing it and I was surprised at how much there is to actually say about users and group, the biggest chapter to date. I’ve learnt a fair bit about the new features of the latest release and discovered a couple of tricks along the way. I can’t wait to share them!

I’ll post progress reports in the blog. That’ll keep me motivated to keep writing and also this will whet your appetite to want to learn more about what I’m currently doing. Some of you may think you don’t need this kind of training and you might be right, but can you answer this question quickly off the top of your head?

“Which objects would you use to add a user to a branch with the editor role using the CSSDK?”

The answer, as it happens, is in the training course so I wont actually give you it straight away. Oh, and if anyone from HP is reading this, you can buy my company any day of the week and improve your offering (ooh, controversial)!

LDAP configuration

Posted: 22 January 2010 in Architecture, Security, Teamsite, Users

To enable LDAP authentication for the teamsite environment, you need to look in the file

conf/roles/user_databases.xml

This file details each ldap server to connect to to authenticate the users. The root element is iwuser_databases and it contains iwldap elements defining each ldap direfctory you would like to use. The iwldap element contains the following sub elements:

  • server: the ip address or host name of the ldap server
  • port: the port number where the ldap server is linstening on. This is usually 389.
  • search_key: when searches are performed, what teamsite user field is being passed to the ldap server. This is where the account name is stored in the ldap. Leave this at uid in most cases.
  • dnBase: which ldap directory part contains the list of users.
  • attr_email: The ldap field that teamsite can use as the email address.
  • attr_display_name: the ldap field that teamsite will use to display user information on.
  • Additional elements are present to connect to the ldap and pass authentication to it:
  • ssl_port: to connect to the secure ldap server
  • CAFile: the path to the certificate authority file.
  • account: the username to connect to the ldap with (for non anonymous queries)
  • password: the ecrypted password to pass along with the username to connect to the ldap.

To retrieve the encrypted version of the password you want to pass, follow the following procedure:

IWCLT_PASSWORD="passwordIWantToEncrypt"
export IWCLT_PASSWORD
iwuseradm encrypt-userdatabase-pwd

This outputs a string to the standard output. Copy this as the value of the password element.

The iwldap element also has the following attributes:

  • id: internally unique identifyer to this ldap entry.
  • display_name: what the user administrator sees when querying the ldap, to select in the drop-down list when adding users for example.
  • os: either “t” or “f”, respectively for true or false. t indicates that a valid os account must also be associated with this ldap entry. f indicates that this ldap contains entries not associated with os accounts.

users can be synchronised with the ldap automatically (possibly the wrong choice of wording here from iwov!). That means that in that case, users get added to the ldap – not to teamsite. and it’s the ldap that manages the users on teamsite’s behalf. This is done by adding an attr_sync element. The ldap entry will in this case also contain which access is granted to a user in teamsite. The ldap field can contain the values

  • master,
  • tsuser,
  • ccpro,
  • ccstd,
  • ccpro_only,
  • ccstd_only,
  • or a comma-separated combination of the above, provided it makes sense (e.g. master|tsuser, ccpro|ccstd,ccpro_only|ccstd_only).

Which ldap field you use for this information is up to you. All you need to do is reference it in the name attribute of the attr_sync element. If you want to have the users added to teamsite manually with reference to the ldap, simply do not include the attr_sync element.

The allowed element inside text, textarea, select, radio, checkbox, readonly and hidden works fine on datacapture forms within forms publisher. Whenever a workflow instantiation form uses the allowed element, it’s not using it to use the instance designed by it.

<item pathid=”somepath” name=”somepath”>
<text>
<allowed><cred role=”master” /></allowed>
</text>
<readonly />
</item>

This snippet of XML should have allowed masters to edit the field and anyone else would just be able to look at it without modifying it. Though this works fine in forms publisher, the workflow engine’s rendition does not concern itself with such authorisation.

Instead, formAPI has to be used. To find out the current user’s name, group and roles, we can use the IWDatacapture’s getUser(), getGroups() and getRoles() methods and show or hide the fields as we please.

getUser() returns the short username (not “Laurent Picquet” but “lpiquet”), getGroups() returns an array of group names the current user belongs to and getRoles() returns an array of roles the current user has in the the current branch (“admin,master” in my case).

var roles = IWDatacapture.getRoles();
 var isMaster=false;
 for (var i in roles){
 if (roles[i]=='master'){
 isMaster=true;
 }
 }
 prompt("isMaster",isMaster);

This is a 4 step process.

  1. We need to define a custom operation that points to the workflow, 
  2. We use the operation in the menu so that users can do the invoking.
  3. We make the toolkit so that teamsite accepts our new operation
  4. We grant people the right to use our operation

 Defining a custom operation

In the teamsite/local/config/lib/content_center/customer_src/etc/conf/customer folder, the file userops_custom.xml is the one we want to modify.

<custom-operations>
<operation description="Calls the workflow to create a new intranet site" display-name="New Site (Intranet)" id="acme.newsite.intranet" />
</custom-operations>

The id must be unique throughout the system. The operation itself does not do anything, it is used later to find who’s allowed to use the action before the action is checked from the link.

Modifying the menu

In order to modify a menu, you need to find where to place it. For that, navigate to the application folder teamsite/httpd/webapps/content_center/WEB-INF/conf/ccpro and view the file ui_common.xml

In this example, we want to create a link below the File > New Site menu option. Looking at the link when we hover over it gives us the “iw.livesite.ccpro.create_site” command. Now we know that, we can find the file this menu has been created in with this little script:

command="iw.livesite.ccpro.create_site"
for file in `find teamsite/local/config/lib/content_center/reference/etc/conf/ -name ui*.xml 2>/dev/null`
 do
  echo ${file}
  cat ${file} | grep ${command}
 done

Open the file given as containing the command (and therefore the link using it) and find the command again.
We need to customise our customisation file called ui_custom.xml with the containing element (and all its parent hierarchy to the action list).

<iwov-ui>
    <action-list id="iw.ccpro.filesys.menubar">
        <menu id="iw.ccpro.file.menu">
        </menu>
    </action>
</iwov-ui>

We need to insert a menu item, below the link to create a new site.

<iwov-ui>
    <action-list id="iw.ccpro.filesys.menubar">
        <menu id="iw.ccpro.file.menu">
            <iwov-insert-after id="iw.livesite.ccpro.file_menu.create_site.link">
                 <link id="acme.file.newsite.intranet"
                        label="New Site (Intranet)"
                        description="Creates a new intranet site"
                        url="/iw-cc/command/iw.ccpro.new_job?iw_template_file=intranet_new_site&amp;iw_template_name=intranet_new_site&amp;workflowType.flag=true"
                        target="_blank"
                        operationID="acme.newsite.intranet"/>
            </iwov-insert-after>
        </menu>
    </action>
</iwov-ui>

Making the toolkit

Navigate to teamsite/local/config/lib/content_center/customer_src and issue the following command as root

./make_toolkit.sh

Granting rights

 Now we’ve done all the hard work, All we need to do is give the operation to one of the roles. For example, admin. On the administration tab, select the manage roles and expand the custom operations part for the admin role.

Getting a connection to the TeamSite server is not a complicated story. The process has 2 steps. First, we get a Factory object which is responsible for returning a client given a transport layer. CSLocalFactory works with JNI and CSSOAPFactory works with SOAP.

Factories

By default, connection properties are defined in a configuration file and you can find one directly in the cssdk subdirectory of the TeamSite installation directory, named cssdk.cfg. We’ll use that file to create a factory of the right type.

String configFilePath = "/apps/interwoven/teamsite/cssdk/cssdk.cfg";
Properties localProperties = new Properties();
localProperties.setProperty("cssdk.cfg.path", configFilePath);
CSLocalFactory csLocalFactory = (CSLocalFactory) CSLocalFactory.getFactory(localProperties);

Clients

Once the factory has been created, we can use it to create a client for us. The client must be authenticated so here we really have 2 choices: we can either give the factory a username and password, or we can tell it to find out who we are from the operating system and log us in directly.

CSClient client = csLocalFactory.getClientForCurrentUser(Locale.ENGLISH, "MyAppName", "localhost");