SuSE Linux (SLES) 11: SSH authentication via Kerberos (GSSAPI) with PuTTY and Windows Server 2008

After many days of trial and error, today I finally managed to automatically log on to my SuSE Linux 11 (SLES11) server with PuTTY using Kerberos authentication by a Windows Server 2008. Here are the exact steps I followed to reproduce the working configuration:

Follow the setup described in Michele’s blog: Active Directory and Apache Kerberos authentication and Putty, Active Directory and Kerberos. However, for creating the keytab file, follow my instructions below. Michele generates his keytab file with this command on the Linux server:

net ads keytab add -U administrator

This associates the Service Principal Name (SPN) of your Linux server with its machine account in the Active Directory. However, the machine account’s password gets reset by the Active Directory on a regular basis and when this happens, the KVNO in the Active Directory gets incremented, but this is not reflected in the Linux server’s keytab and suddenly Kerberos does not work anymore. You may get an error like this in the SSH log:

sshd[30106]: debug1: Unspecified GSS failure.  Minor code may provide more information\nKey version number for principal in key table is incorrect\n

So instead of using the machine’s account, we will use a (technical) user account specifically created for this task, that has a password which never expires. Therefore, its KVNO never changes and Kerberos will continue to work (or at least I hope so ;-) ).

  1. Make sure that no account in the Active Directory has the SPN of the Linux server you want to log on to. Even delete the SPN from the Linux machine’s account itself! You can use the attribute editor (or ADSI editor) on the server. Check the SPN with this command:
    ldifde -f c:\spn_out.txt -d “DC=yourdomain,DC=com” -l *,msDS-KeyVersionNumber -r “(serviceprincipalname=HOST/yourlinuxhostname*)” -p subtree

    The result should show 0 entries! Otherwise you may get a message like the following in PuTTY’s event log:

    The target was not recognized (SEC_E_TARGET_UNKNOWN)
  2. Create a user account in the Active Directory that you want to associate with the Linux server, e.g. tukerberos. Set the account’s password and make sure to configure it to never expire.
  3. Associate the user account with the SPN of the Linux server with this command:
    ktpass -princ host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM -mapuser yourdomain\tukerberos -ptype KRB5_NT_PRINCIPAL -pass USERPASSWORD -crypto All -out c:\krb5.keytab

    The output should look like this:

    Targeting domain controller: dc.yourdomain.com
    Using legacy password setting method
    Successfully mapped host/yourlinuxhostname.yourdomain.com to tukerberos
    .
    Key created.
    Key created.
    Key created.
    Key created.
    Key created.
    Output keytab to c:\krb5.keytab:
    Keytab version: 0x502
    keysize 101 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x1 (DES-CBC-CRC) keylength 8 (0x46629e67156b3b40)
    keysize 101 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x3 (DES-CBC-MD5) keylength 8 (0x46629e67156b3b40)
    keysize 109 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0149b059adfce2da6ae4319fbcf100f0)
    keysize 125 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32 (0x9a9c4dad7b65d0b294164dce8bbd5b4b39d674741bca1ef4f1583e6a8e77313b)
    keysize 109 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x11 (AES128-SHA1) keylength 16 (0xcc466c3cd0e3828f91a60556058a29b5)

    If you run the ldifde command from above again, you should now get a result of 1 entry for tukerberos!

  4. Copy the file c:\krb5.keytab over to the Linux server as /etc/krb5.keytab.
  5. If you run klist -kte on the Linux server now, you should see 5 entries for its SPN:
    Keytab name: FILE:/etc/krb5.keytab
    KVNO Timestamp         Principal
    ---- ----------------- --------------------------------------------------------
       3 01/01/70 01:00:00 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM (DES cbc mode with CRC-32)
       3 01/01/70 01:00:00 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM (DES cbc mode with RSA-MD5)
       3 01/01/70 01:00:00 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM (ArcFour with HMAC/md5)
       3 01/01/70 01:00:00 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM (AES-256 CTS mode with 96-bit SHA-1 HMAC)
       3 01/01/70 01:00:00 host/yourlinuxhostname.yourdomain.com@YOURDOMAIN.COM (AES-128 CTS mode with 96-bit SHA-1 HMAC)
  6. To make sure that no already existing tickets are used, purge your local ticket cache using kerbtray.exe on your Windows client and run the following command on your Linux server:
    kdestroy
    kinit Administrator
  7. Try logging on to your Linux server with PuTTY. It should work now :-)

Further reading

Setting the position of guidelines in PowerPoint from a VBA script

As I had to find out today, you cannot set the position of guidelines in PowerPoint from a VBA macro. But if you need a set of accurately positioned guidelines like shown in the screenshot below (exactly 32 vertical guidelines with the same distance between them), it would be almost impossible to position them by hand.

Accurately positioned PowerPoint guidelines

However, as you may know, PowerPoint’s PPTX files are simply zipped XML files, that can be extracted, analyzed (e.g. diffed), and modified. So I did exactly that and found out that the presentation’s guidelines are defined in ppt\viewProps.xml.

PowerPoint viewProps.xml

Having placed a single vertical guideline at both ends of the slide in an empty presentation, the corresponding part in viewProps.xml looks like this:

  1. <p:guideLst>
  2.         <p:guide orient="horz" pos="2160"/>
  3.         <p:guide />
  4.         <p:guide pos="5760"/>
  5. </p:guideLst>

So, the rightmost position of a guideline in PowerPoint’s internal unit of measurement (whatever that is) is 5760. Now you can divide this number by the number of guidelines you would like to have (32 in my case) and add new lines to the XML file accordingly:

  1. <p:guideLst>
  2.         <p:guide orient="horz" pos="2160"/>
  3.         <p:guide />
  4.         <p:guide pos="180"/>
  5.         <p:guide pos="360"/>
  6.         …
  7.         <p:guide pos="5760"/>
  8. </p:guideLst>

Now you can zip up the folder again, rename the file to pptx and open it in PowerPoint.

As the title of this blog post suggests, the above process could be automated. However, as zip file handling is not built in into PowerShell at the moment, I leave this exercise for the reader ;-)

Unit-testing Flow Services in webMethods’ Integration Server with JUnit

Today, I built a small test bed for unit-testing Flow Services in webMethods’ Integration Server. If you develop Java Services for IS and follow the best practice of “no business logic in the service layer”, you can unit-test your logic in isolation in a plain old Java environment and deploy the library to IS, which then only acts as the service bus and simply forwards service calls to the library. However, if you create Flow Services directly in IS, which can get complicated pretty fast, I found no built-in tool for testing their logic. Here’s an example of a small Flow Service:

webMethods Flow Service

So I went ahead and created a local Java project, in which I could unit-test the remote services. I know network access in unit-tests is considered a “boundary” which should not be crossed, because tests run slower and may fail due to network problems. However, I would rather have a suite of (relatively) slow running tests for my important services than have no tests at all and see programs fail due to regression. And debugging services in IS is no fun at all!

Calling the IS services directly from Java is surprisingly easy. Software AG Designer generates all the needed source code for you. Right-click on the service and choose Generate Code. Then follow the steps in the wizard:

Calling IS Service Wizard 1
Calling IS Service Wizard 2
Calling IS Service Wizard 3

The generated code is executable directly, as long as you add references to IS’ client.jar and enttoolkit.jar to your Java project.

Testing IS Services References

The service call itself is implemented in this simple method:

  1. public static IData invoke(Context context, IData inputDocument)
  2.     throws IOException, ServiceException
  3. {
  4.      IData out = context.invoke("PACKAGE", "NAME", inputDocument);
  5.      IData outputDocument = out;
  6.      return outputDocument;
  7. }

However, as you can see above, the service accepts and returns IData objects, whose construction is not that easy and should not be scattered throughout your test code. Even providing a simple value requires at least the following code. And the code for getting the value out of IData to be able to call an assertion on it looks similar.

  1. IData out = IDataFactory.create();
  2. IDataCursor idc = out.getCursor();
  3. idc.insertAfter("errorFlag", "true");
  4. idc.destroy();

So, to make life easier for me, I spent some time and developed a small environment, in which I can work with plain old Java objects for service input and output in my tests and assert against the public fields of these objects, like this example of a simple date conversion service demonstrates:

  1. protected ConvertDateToN8 sut;
  2. protected ConvertDateToN8.Input input;
  3.  
  4. @Test
  5. public void shouldConvertValidDate() throws Exception
  6. {
  7.     input.Date = "2008-10-15";
  8.     ConvertDateToN8.Output output = sut.call(input);
  9.     assertThat(output.DateN8, is("20081015"));
  10. }

The service class looks like this:

  1. public class ConvertDateToN8 extends ServiceCall<ConvertDateToN8.Input, ConvertDateToN8.Output>
  2. {
  3.     public class Input extends ServiceInput
  4.     {
  5.         public String Date;
  6.     }
  7.  
  8.     public class Output extends ServiceOutput
  9.     {
  10.         public String DateN8;
  11.     }
  12.  
  13.     public ConvertDateToN8(String host)
  14.     {
  15.         super(host, "Common", "ConvertDateToN8");
  16.     }
  17.  
  18.     public Input createInput()
  19.     {
  20.         return new Input();
  21.     }
  22.  
  23.     @Override
  24.     protected Output createOutput()
  25.     {
  26.         return new Output();
  27.     }
  28. }

The only thing that needs to be added to the project to test another service is a class like the one above. I can simply define the input and output of the service in nested classes and everything else is magically built with generics and reflection. Here is an example of converting the generic Input object to IData in class ServiceCall:

  1. protected IData createPipelineFromInput(ServiceInput input)
  2. {
  3.     IData pipeline = IDataFactory.create();
  4.     IDataCursor idc = pipeline.getCursor();
  5.  
  6.     Class<?> c = input.getClass();
  7.     for (Field publicField : c.getFields())
  8.     {
  9.         try
  10.         {
  11.             String fieldName = FieldNameConverter.convertToPipelineName(publicField.getName());
  12.             Object fieldValue = FieldConverter.convertToPipeline(publicField.getType().getName(), publicField.get(input));
  13.             IDataUtil.put(idc, fieldName, fieldValue);
  14.         }
  15.         catch (Exception e)
  16.         {
  17.             e.printStackTrace();
  18.         }
  19.     }
  20.     idc.destroy();
  21.  
  22.     return pipeline;
  23. }

Even more complex data structures like objects or arrays can be constructed by extending the classes FieldConverter and PipelineConverter which encapsulate the access to IData:

  1. public class Input extends ServiceInput
  2. {
  3.     public String errorFlag;
  4.     public String errorCode;
  5.     public String errorMessage;
  6.     public NaturalErrorInfo ERROR_INFO;
  7. }

You can take a look at the implementation for converting the above input to and from IData in the source code, which can be downloaded below. Feel free to take a look at it and contact me for questions or additions!

Download

Permanently setting Windows environment variables from scripts (e.g. PowerShell)

To permanently set Windows environment variables (e.g. PATH) from a (PowerShell) script, you can use setx or Set-ItemProperty like this (for the current user):

setx VARIABLE value
Set-ItemProperty -Path 'Registry::HKEY_CURRENT_USER\Environment' -Name VARIABLE -Value "value"

And here is the result:

Setting Environment Variables From A Script

Ausbildungsplatz zum Fachinformatiker Anwendungsentwicklung bzw. Duales Studium Wirtschaftsinformatik zum 01.08.2013 in Vechta

Wie in den letzten Jahren bietet die ALTE OLDENBURGER Krankenversicherung AG

Logo ALTE OLDENBURGER

auch in diesem Jahr wieder einen Ausbildungs-/Studienplatz im EDV-Bereich an: Zum 01.08.2013 suchen wir

  • einen Auszubildenden (m/w) zum Fachinformatiker Anwendungsentwicklung bzw.
  • einen dualen Studenten (m/w) der Wirtschaftsinformatik in Zusammenarbeit mit dem Department für duale Studiengänge der Fachhochschule Osnabrück am Studienstandort Lingen.
Logo BA Emsland

Hier geht es zur kompletten Stellenanzeige mit Anschrift für die Bewerbungsunterlagen: Stellenangebote bei der ALTE OLDENBURGER.

Weitere Informationen zum Ausbildungsberuf Fachinformatiker Anwendungsentwicklung gibt es auf der Website der ALTE OLDENBURGER sowie bei der IHK Oldenburg und der BBS Haarentor. Der Studiengang Wirtschaftsinformatik wird auf der Website der BA Emsland im Detail beschrieben: Studiengang Wirtschaftsinformatik bei der BA Emsland.

Ich freue mich auf alle Bewerbungen und vielleicht arbeiten wir bald zusammen :-)

Installing and configuring MikTeX, TeXlipse, and Pdf4Eclipse to write and compile LaTeX documents

Setting up a “development” environment for LaTeX is quite complicated compared to installing Microsoft Word ;-) And it gets even more complicated, if you decide to use Eclipse as the platform for writing your documents. However, as I had to setup such an environment from scratch today, here’s how I did it with minimum impact on the system.

  1. (Optionally) create a base directory in which all of the programs below will get installed, e.g. D:\LaTeX.
  2. Download MikTeX – Portable Edition and extract it to D:\LaTeX\MikTeX.
  3. Download and install the JDK: Java SE Downloads. If you have security concerns like me, make sure to download the latest version and enable daily updates and/or disable the Java plugin in your browser.
  4. Download Eclipse (the most basic version will do, e.g. “classic” or “for Java developers”) and extract it to D:\LaTeX\Eclipse.
  5. Start Eclipse and choose a convenient path for the workspace (where your LaTeX projects will get saved), e.g. D:\LaTeX\Workspace.
  6. Install TeXlipse into Eclipse: Help – Install New Software – Add a new repository with name “TeXlipse” and location “http://texlipse.sourceforge.net/”. Select all installable items as shown below. As you can see, Pdf4Eclipse will already be installed, too.
    Installation of TeXlipse
    Simply click through the installation wizard and restart Eclipse after the installation is finished.
  7. After TeXlipse is installed, you should already be able to open the LaTeX perpective in Eclipse.
    Open the LaTeX perspective in Eclipse
  8. Now it’s time to tell TeXlipse where it can find your LaTeX executables and therefore be able to compile your LaTeX documents. Go to Window – Preferences – Texlipse – Builder Settings, enter the path to your MikTeX executables – D:\LaTeX\MikTeX\miktex\bin – into Bin directory of TeX distribution, and click Apply. That should automatically fill in all the needed programs in Programs used for building the document for you.
    Configure TeXlipse to use MikTeX
  9. Now you should already be able to create and compile your first LaTeX project. Right-click into your Project Explorer and create a new project.
    Create a new LaTeX project with TeXlipse
    Create a new LaTeX project with TeXlipse (2)
    If you save document.tex, it should automatically be compiled. Take a look at the corresponding console output.
    Compiling a LaTeX project with TeXlipse
  10. If you double-click on the created document.pdf file in the Project Explorer (a Refresh may be needed to show the file), it should be opened with Pdf4Eclipse. If you double-click a line in the PDF file, Eclipse should now jump to the corresponding position in your LaTeX source.

And that’s it! Now you can start writing your LaTeX document. If you need a template, take a look at these blog posts (they are in German):

Growing Object-Oriented Software, Guided by Tests (Freeman/Pryce)

Nachdem “Growing Object-Oriented Software, Guided by Tests” von Steve Freeman und Nat Pryce bei den Ruby Rogues besprochen wurde (siehe 068 RR Book Club: Growing Object Oriented Software Guided by Tests), war mir klar, dass ich es auch lesen musste. Und ich muss sagen: es hat sich definitiv gelohnt. Es ist das beste Buch zum Thema Test Driven Development, das ich bislang gelesen habe.

Das Buch beginnt mit einer ca. 70-seitigen allgemeinen Einführung in das (testgetriebene) Vorgehen der Autoren bei der Softwareentwicklung. Dabei wird z.B. TDD erläutert und die eingesetzten Werkzeuge werden vorgestellt. Der Fokus liegt hierbei auf JUnit und jMock.

Danach folgt ein riesiges Praxisbeispiel: ein “Auktionssniper”, dessen Entwicklung als Java-Swing-Anwendung auf gut 150 Seiten beschrieben wird. Was mir dabei die Augen geöffnet hat, war das Starten mit einem fehlschlagenden Akzeptanztest. Bevor die erste Zeile Produktiv- bzw. Unit-Test-Code geschrieben wurde, haben die Autoren viel Zeit darauf verwendet, einen “End-To-End-Test” zu erstellen, der die erste Funktionalität der Applikation wie ein echter Benutzer testet. Dazu ist einiges an Aufwand nötig (Threading, GUI-Test-Framework etc.), aber das lohnt sich im Nachhinein, weil die Tests mit echten Benutzern entfallen können.

Ich muss zugeben, dass ich das Praxisbeispiel teilweise nur recht schwer nachvollziehen konnte, weil ich beim Lesen nicht den ganzen Code im Kopf hatte und immer nur die interessanten Teile gezeigt wurden. Allerdings konnte ich sehr viele Anregungen für meine eigenen Anwendungen mitnehmen, z.B. dass man generische Klassen nicht als Methodenparameter nutzen sollte (sondern besser eine eigene Containerklasse mit einem sinnvollen Namen erstellen sollte), dass einem die “import”s einer Klasse ggfs. verraten, dass diese zu viele Aufgaben hat, oder dass man Factorys besser im Kontext der Domäne benennen sollte (z.B. AuctionHouse anstatt AuctionFactory).

Abgerundet wird das Buch durch die letzten ca. 100 Seiten mit wieder eher allgemeinen Tipps zum testgetriebenen Entwickeln. Dabei gehen die Autoren noch einmal in die Vollen und behandeln z.B. das Testen von Multithreading-Applikationen oder den sinvollen Umgang mit Logging-Mechanismen.

Alles in allem kann ich dieses Buch jedem Softwareentwickler empfehlen. Obwohl die Beispiele in Java geschrieben sind, lassen sie sich leicht auf andere Sprachen übertragen und jeder Entwickler wird hier eine Vielzahl an Anregungen für die Programmierung mitnehmen können.

Enable daily Java Updates in Windows 7 (64bit)

Java has had quite a few security issues recently. Therefore, it definitely makes sense to enable the Java Updater and to install every Java update right after Oracle releases it. However, on my different Windows (64bit) boxes I could not configure the Java Updater. There was simply no “Update” tab in the Java control panel.

I found the solution here: Missing Java update tab. Possibly due to permission problems, Java did not add the following key to the registry: HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Update\Policy\EnableJavaUpdate. After I added it (DWORD, value 1), the “Update” tab was shown, but I was not able to save the changes I made to the update interval. The solution to this problem can be found here: Why are the Java update settings not saved in the Java control panel?. You have to start the Java control panel (javacpl.exe) as an Administrator.

To save me the pain of repeating the steps above on all my Windows machines, here is a file that can be imported directly into the Windows registry and sets the update interval to daily (9:00 AM):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Update\Policy]
"EnableJavaUpdate"=dword:00000001
"NotifyDownload"=dword:00000000
"NotifyInstall"=dword:00000001
"Frequency"=dword:0000007f
"UpdateSchedule"=dword:00000009

Download the file: Enable daily Java updates in Windows registry.

Database is locked when committing to a Subversion repository

I added a new Subversion repository on our Debian webserver today and got the following error messages when committing to it:

[Wed Oct 10 ...] [error] [client ...] mod_dav_svn close_stream: error closing write stream  [500, #200029]
[Wed Oct 10 ...] [error] [client ...] Couldn't perform atomic initialization  [500, #200029]
[Wed Oct 10 ...] [error] [client ...] database is locked  [500, #200030]

Our repositories are hosted on a Windows fileserver and are mounted to the local Linux filesystem. In my case, the solution to the problem was to mount the Samba share using the parameters nolock,rw in /etc/fstab like this:

//fileserver/SVNRepository    /home/svn    smbfs    user=username,pass=secret,dom=MYDOM,uid=33,gid=33,nolock,rw    0    0

Logging to webMethod’s Integration Server log from a Java Service

I created a Java Service in webMethod’s Integration Server that should log something to the server.log file. As it turns out, this is quite simple:

  1. Generate Java code for calling the internal Service pub.flow.debugLog by right-clicking on the Service in Software AG Designer and selecting “Generate Code…”, “For calling this service from another service”. The code gets copied to the clipboard automatically.
  2. Paste the code snippet into your Java Service. It may look like this:
    1. // input
    2. IData input = IDataFactory.create();
    3. IDataCursor inputCursor = input.getCursor();
    4. IDataUtil.put( inputCursor, "message", "message" );
    5. IDataUtil.put( inputCursor, "function", "function" );
    6. IDataUtil.put( inputCursor, "level", "level" );
    7. inputCursor.destroy();
    8.  
    9. // output
    10. IData   output = IDataFactory.create();
    11. try{
    12.         output = Service.doInvoke( "pub.flow", "debugLog", input );
    13. }catch( Exception e){}
  3. Now you’ll need a reference to the JAR file containing the needed classes (i.e. com.wm.data.IData, IDataCursor, IDataUtil, and com.wm.app.b2b.server.Service). The former can be found in client.jar (e.g. \SoftwareAG\eclipse\v36\plugins\com.webmethods.process.model.upgrade.impl_8.2.2.0000-0211\lib\client.jar), the latter in wm-isserver.jar (e.g. SoftwareAG\IntegrationServer\lib\wm-isserver.jar). Add the JARs to your project’s build path and your done. Now you should be able to compile your project.

I’ve created a short helper method for accessing the logging from a Java Service to get rid of the redundant code snippets:

  1. public static void logMessageToServerLog(IData pipeline, String message, String function, String level) throws ServiceException
  2. {
  3.         IDataCursor inputCursor = pipeline.getCursor();
  4.         IDataUtil.put(inputCursor, "message", message);
  5.         IDataUtil.put(inputCursor, "function", function);
  6.         IDataUtil.put(inputCursor, "level", level);
  7.         inputCursor.destroy();
  8.  
  9.         try
  10.         {
  11.                 Service.doInvoke("pub.flow", "debugLog", pipeline);
  12.         }
  13.         catch (Exception e)
  14.         {
  15.                 throw new ServiceException(e.getMessage());
  16.         }
  17. }