LSC Use Case: synchronize telephoneNumber from Sun LDAP to Active Directory

July 21st, 2010 1 comment

At work, we are using two directories. The first one, a damn old Sun Directory 5.2, used by the mail system and VOIP. The second directory is an Active Directory used by … everything which run on Windows. At the moment, we don’t have some Identity Provisionning products, so users are created by hand in both directories. I want to make this synchronization automatic, however since it’s a complex and dangerous thing, I want to start by synchronize few attributes. The first one is the telephoneNumber, available in the Sun Directory with format “21xxx” (the internal phone number), while the one store in active directory is the public one (014070xxx), so I need to transform the attribute before sending it in AD.

Some friends of mine start the LSC Project(LDAP Synchronization Connector) few years ago, a tool to synchronize directories! Here the configuration file I used for my use case:

Define the source


src.java.naming.provider.url = ldap://sun_hostname:389/dc=rtl,dc=fr
src.java.naming.security.authentication = none
src.java.naming.security.principal =
src.java.naming.security.credentials =
src.java.naming.referral = ignore
src.java.naming.ldap.derefAliases = never
src.java.naming.factory.initial = com.sun.jndi.ldap.LdapCtxFactory
src.java.naming.ldap.version = 3

Define the target


dst.java.naming.provider.url = ldap://ad_hostname:389/dc=activedirectory,dc=domain
dst.java.naming.security.authentication = simple
dst.java.naming.security.principal = userwithenoughperms@activedirectory.domain
dst.java.naming.security.credentials = secret
dst.java.naming.referral = ignore
dst.java.naming.ldap.derefAliases = never
dst.java.naming.factory.initial = com.sun.jndi.ldap.LdapCtxFactory
dst.java.naming.ldap.version = 3

Define the task to manage telephoneNumber attribute


lsc.tasks = FirstTask
lsc.tasks.FirstTask.srcService = org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.FirstTask.srcService.baseDn = ou=People
lsc.tasks.FirstTask.srcService.filterAll = (inetUserStatus=ACTIVE)
lsc.tasks.FirstTask.srcService.pivotAttrs = mail
lsc.tasks.FirstTask.srcService.filterId = (mail={mail})
lsc.tasks.FirstTask.srcService.attrs = mail telephoneNumber
lsc.tasks.FirstTask.srcService.requestNameForList = getAllPeoplePivots
lsc.tasks.FirstTask.srcService.requestNameForObject = getOnePerson
lsc.tasks.FirstTask.dstService = org.lsc.jndi.SimpleJndiDstService
lsc.tasks.FirstTask.dstService.baseDn = ou=Pole radio,dc=activedirectory,dc=domain
lsc.tasks.FirstTask.dstService.filterAll = (&(sn=*)(objectClass=inetOrgPerson))
lsc.tasks.FirstTask.dstService.pivotAttrs = mail
lsc.tasks.FirstTask.dstService.filterId = (mail={mail})
lsc.tasks.FirstTask.dstService.attrs = telephoneNumber
lsc.tasks.FirstTask.bean = org.lsc.beans.SimpleBean
lsc.tasks.FirstTask.dn = ""
lsc.syncoptions.FirstTask = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.FirstTask.default.action = K
lsc.syncoptions.FirstTask.default.delimiter = $
lsc.syncoptions.FirstTask.telephoneNumber.action = F
lsc.syncoptions.FirstTask.telephoneNumber.force_value = StringUtils.replaceFromMap(srcBean.getAttributeValueById("telephoneNumber"), "telephone.csv")

I think most of properties are self-meaning, however here some explanations about few of thems

  • default.action = K, meaning the attribute is not overriden if the value is ok
  • telephoneNumber.action = F, force the attribute to be updated
  • lsc.syncoptions.FirstTask.telephoneNumber.force_value= StringUtils.replaceFromMap(srcBean.getAttributeValueById(“telephoneNumber”), “telephone.csv”) is the code to compute the new value of the telephoneNumber attribute. In that case, I use a CSV files where I specify two fields: the pattern, and the value to replace if the pattern is found. (i.e. “^21,014070”)

Output in dryrun mode


% ./bin/lsc -n -f etc -s FirstTask
juil. 21 16:24:43 - WARN - Starting sync for FirstTask
juil. 21 16:24:43 - INFO - Connecting to LDAP server ldap://sun_hostname:389/dc=rtl,dc=fr anonymously
juil. 21 16:24:44 - INFO - Connecting to LDAP server ldap://ad_hostname:389/dc=activedirectory,dc=domain as admin@activedirectory.domain
juil. 21 16:24:44 - WARN - The method getAttributeValueById() is deprecated and will be removed in a future version of LSC. Please use getAttributeFirstValueById() instead.
juil. 21 16:24:44 - DEBUG - Update condition false. Should have modified object CN=BONFILS Bruno,OU=Users,DC=activedirectory,DC=DOMAIN
dn:: CN=BONFILS Bruno,OU=Users,DC=activedirectory,DC=DOMAIN
changetype: modify
replace: telephoneNumber
telephoneNumber: 0140704049

juil. 21 16:24:44 - INFO - All entries: 1, to modify entries: 0, modified entries: 0, errors: 0

Categories: IAM Tags:

ZSH: Create dynamically associatives array in a function

July 14th, 2010 No comments

I’m currently working on some scripts to create CSV files (to import into iTop, I’ll post about it in few weeks) from data received via snmp. To make things propers, I want to reuse my code as far as possible, so I was looking for a way to create some associatives array in a function, where the array name is give as argument.

Thanks to the ZSH IRC channel (special thanks to ft) here a way to achieve that:


mytest() {
typeset -A -g $1
buffer="$1[$2]"
: ${(P)buffer::=$3}
}

so, the following sample code:


mytest() {
typeset -A -g $1
buffer="$1[$2]"
: ${(P)buffer::=$3}
}

mytest toto 3 42
mytest tutu 4 43

print -l $toto[3]
print -l $tutu[4]

will display 42, and then 43!

One final word: zsh is magic.

Categories: Shell, Sysadmin Tags:

Splunk: useful URL

July 11th, 2010 No comments

as you probably already know IRC is good to learn things, here some URL I learn from the splunk channel:

  • http://host:webport/en-US/debug/refresh reload some parts of splunk, including applications’s views. Very useful when developing a new application. No need to restart each time!
  • https://host:8089/services/admin/inputstatus/TailingProcessor:FileStatus display the status of file monitorings. Note the port is the manager one, not the webone, so I guess this interface is available on agents even if splunkweb is not started. You can hit /services/admin/ to find another log of informations.
Categories: Business tools Tags:

Bandwidth monitor: simple but efficient

June 21st, 2010 No comments

Today, I was looking for a small tool to display interface usage on Solaris, I tried first iftop. However, after spent few hours to try to build it (including ncurses, libpcap) I finally got a binary, but it’s not working! After google for few minutes, I found Bandwitdth monitor NG. It’s a very simple software, which uses only few libraries, and works like a charm!

Here a snapshot:

Bandwith Monitor NG screenshot

And for information, ldd output :

% ldd /opt/tools/bwm-ng-0.6/bin/bwm-ng
libcurses.so.1 => /lib/libcurses.so.1
libkstat.so.1 => /lib/libkstat.so.1
libc.so.1 => /lib/libc.so.1
libm.so.2 => /lib/libm.so.2

Categories: OpenSolaris, Solaris Tags:

How to clone search’s dashboard in splunk

June 14th, 2010 No comments

After few weeks trying to persuade my boss to buy Splunk, I start to put it in production. My first goal was to clone the search application’s dashboard using a dedicated index. Indeed, I have few splunks agent reading some tomcat’s logs and forward them to my splunk instance. All these logs are going to a dedicated index, named rtlnet. Our webdeveloppers want to use splunk to see the production’s logs. While it was easy to create the rtlnet index, I wanted to clone the search’s dashboard to give them an overview of logs by application, or by host. However, while it was easy to add index=rtlnet in the metadata search, I was not able to add the index in the search computed when you click on a result (for example the sourcetype).

Here the original code which produce one of the three panel:

      <module name="SearchLinkLister">
        <param name="settingToCreate">list1</param>
        <param name="search">| metadata type=sources</param>
        <param name="searchFieldsToDisplay">
          <list>
            <param name="label">source</param>
            <param name="value">source</param>
          </list>
          <list>
            <param name="label">totalCount</param>
            <param name="labelFormat">number</param>
          </list>
        </param>
        <module name="ConvertToIntention">
          <param name="settingToConvert">list1</param>
          <param name="intention">
            <param name="name">addterm</param>
            <param name="arg">
              <param name="source">$target$</param>
            </param>
          </param>
          <module name="ViewRedirector">
            <param name="viewTarget">flashtimeline</param>
            <param name="uriParam.auto_pause">true</param>
          </module>
        </module>
      </module>

As I said, adding index=rtlnet in the metadata search is trivial. However, when a user click on a result (in that case on a source), the computed search was only source=$target so there was no result, since it the index is not specified. After spending few hours trying to understand how to add the index in the existing intention, I finally understood I need to nest it into a new HiddenIntention. Here the new module definition:

      <module name="SearchLinkLister">
        <param name="settingToCreate">list1</param>
        <param name="search">| metadata type=sources index=rtlnet </param>
        <param name="searchFieldsToDisplay">
          <list>
            <param name="label">source</param>
            <param name="value">source</param>
          </list>
          <list>
            <param name="label">totalCount</param>
            <param name="labelFormat">number</param>
          </list>
        </param>
        <module name="HiddenIntention">
          <param name="intention">
            <param name="name">addterm</param>
            <param name="arg">
              <param name="index">rtlnet</param>
            </param>
          </param>
          <module name="ConvertToIntention">
            <param name="settingToConvert">list1</param>
            <param name="intention">
              <param name="name">addterm</param>
              <param name="arg">
                <param name="source">$target$</param>
              </param>
            </param>
            <module name="ViewRedirector">
              <param name="viewTarget">flashtimeline</param>
              <param name="uriParam.auto_pause">true</param>
            </module>
          </module>
        </module>
      </module>

As you can notice, I embedded the existing ConvertToIntention module in a new HiddenIntention. Cheers!

Categories: Sysadmin Tags:

rsyslog, split file by hostname

June 10th, 2010 1 comment

Here a rsyslog snippet to create a file by day, by device. Indeed, the %now variable take a value like 2010-05-24. Note that HOSTNAME will be replace by the hostname send by the syslog client. If you want to use IP, you can use %fromhost-ip%, and if you want the DNS name resoved by the rsyslog server, use %fromhost%.


$template default,"/data/logs/%HOSTNAME%/%$now%.log"

*.* ?default

Categories: Sysadmin Tags:

Séminaire sysadmin le 2 août

June 4th, 2010 4 comments

Alors que la liste sysadmin@asyd.net va bientôt fêter ses 4 ans d’existence (création le 17 septembre 2006), avec un total de 157 abonnés, nous commençons l’organisation du premier séminaire.

Au programme :

Horaire Titre Intervenant
9h00 → 9h45 Puppet Alban Peigner
10h00 → 10h45 ZFS ce qui nous plait et comment on l’utilise Olivier Delhomme
11h00 → 11h45 Retour d’expérience sur la haute disponibilité Arnaud Gomes Do Vale
14h00 → 14h45 Splunk, use case et retour d’expérience Bruno Bonfils
15h00 → 15h45 Annuaire LDAP et interface de gestions Benoît Mortier
16h00 → 16h45 FusionInventory David Durieux
17h00 → 17h45 iTop Erwan Taloc
18h00 → xxx Confs éclairs NA

Pour les confs éclairs, la liste ne fait que commencer, mais on y trouvera :

  • JRDS, un cacti like en Java
  • PowerDNS

N’hésitez pas à vous manifester pour proposer une conf éclair !

Cet événement prendra place à l’école des mines à Paris, 60 Boulevard Saint Michel. Pour des raisons pratiques d’organisation, les participants sont invités à s’enregistrer.

Categories: Sysadmin Tags:

Nagios: check_ldap on Solaris

March 29th, 2010 1 comment

A personal note about how to get check_ldap (Nagios’s plugins) on Solaris, you simply need to edit the configure file itself to remove -llber from the line LIBS=”-lldap -llber $LIBS”. You also need to execute the following commands:

perl -i -pe ‘s/-lldap -llber/-lldap/g’ **/*Makefile

Cheers!

Categories: Monitoring Tags:

varnish: Send a client always on the same backend

March 9th, 2010 No comments

I’m now very close to migrate from akamai to varnish at work. However, since we doesn’t have session replications on the application server, I was required to send a client always on the same backend, even if the user is not authentified. In a first try, we thought about use a cookie, valued by the name of the server, and write some VCL to define the backend based on the cookie value.

However, thanks to the varnish developper (through the channel) phk pointed me they’re working on a director method to implements this behavior. While this feature is not yet available on a release, it’s present in the trunk (I’m using r4602).

Here the source code:

if (vs->criteria == c_client) {
/*
* Hash the client IP# ascii representation, rather than
* rely on the raw IP# being a good hash distributor, since
* experience shows this not to be the case.
* We do not hash the port number, to make everybody behind
* a given NAT gateway fetch from the same backend.
*/
SHA256_Init(&ctx);
AN(sp->addr);
SHA256_Update(&ctx, sp->addr, strlen(sp->addr));
SHA256_Final(sign, &ctx);
hp = sign;
}

Here how to define your director:

director rtl client {
{ .backend = www1rtl; .weight = 1; }
{ .backend = www2rtl; .weight = 1; }
}

Categories: Sysadmin Tags:

OpenSSO strict cookie value

February 22nd, 2010 1 comment

At my work, we’re currently working on a new J2EE platform to host our webapp applications, based on Tomcat 6 (6.0.24 to be precise). After deployed few fully public webapps without any issue, we start to deploy some other webapps with an authenticated part. The authentication is based on OpenSSO, using REST APIs. The cookie is created to OpenSSO, then set (client side) by one of our own webapplication. This cookie is validate using isValidToken REST API on every application the user goes. However, we’re not able to get authentication working on the preproduction environment, while it working perfectly on the dev environment. After some investigations with the developpers, we notice the OpenSSO’s cookie value was truncated.

After reading this post on the tomcat’s user mailing list, we start to configure tomcat. Few hours after, I was thinking about change the tomcat configuration is only a workaround, without fixing the original problem. Thanks to the OpenSSO’s IRC channel, someone (Allan Foster) pointed me to com.iplanet.am.cookie.c66Encode configuration variable. You can enable it in the console, Configuration, servers and sites, click on default paramaters, and then advanced tab. Set the value to true, and voila! Everything is now working good!

Categories: IAM, SSO Tags: