Strato-V-Server – Opensuse 13.1 – get colors for the "ls" shell command

Today, I tried to work with a freshly installed Strato-V-Server. I had chosen Opensuse 13.1 (64 Bit) as the operative system. When I used the “ls” command I missed the standard coloring of directories and special files.

Using the “env” command and a comparison with a normal Opensuse 13.1 installation showed that required settings for the “ls” coloring were missing. SuSE normally adds these settings via a script “ls.bash” located in the directory “/etc/profile.d”. However, this file was missing on the Strato server. [The script in turn uses “/usr/bin/dircolors”, which existed on the system.]

You could compensate the lack of coloring by manually adding a line

ls –color=tty

to a local “.bashrc” file. However, this would only give you parts of the SuSE coloring scheme for your shell.

The missing file “ls.bash” is the result of a really minimum Opensuse 13.1 installation provided by Strato on their V-servers. It took me a while to find the right RPM package which installs the required files. It is the RPM aaa_base-extras.

After the installation of this package and a reopening of your shell “env” will show some additional lines that control the “ls” color settings:

user@hxxxxxx:~> env | grep LS
LS_COLORS=no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.xz=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=01;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*.voc=00;32:*.wav=00;32:
...
...
LS_OPTIONS=-N --color=tty -T 0
user@hxxxxxx:~>

I hope this information will help others who miss the the usual “ls”-coloring on Strato-V-servers, too.

fsck on KVM raw device disks

If you have a small company resource optimization is a must. Therefore, I use KVM virtualization to provide several (virtual) servers on a KVM host. The hard disks are provided as raw devices under the control of the KVM “virtio” driver. My virtual machines have been running very reliably for two years now.

However, some days ago one of the servers – a LAMP server called “vm1” – could not be booted any more. Not even its virtual console displayed any messages – the boot process stopped at the very beginning. I took this as a sign to check for corruptions of the file system. In the case of “vm1” the raw device is located on a LVM partition “/dev/volgrpk/vm1_hd1” of a LVM volume group on the KVM host. The internal structure of this device consists of a SWAP partition plus a data partition. The latter one gets mounted on “/” on the virtual guest server.

Because it was such a long time ago that I had to use fsck on a virtual device I had forgotten that you cannot deal directly with KVM raw devices from the KVM host. My naive trial to use fsck directly produced warnings as the KVM host cannot handle KVM raw image devices :

kvm-host:~ # fsck /dev/volgrpk/vm1_hd1 
fsck from util-linux 2.23.2
e2fsck 1.42.8 (20-Jun-2013)
ext2fs_open2: Bad magic number in super-block
fsck.ext2: Superblock invalid, trying backup blocks...
fsck.ext2: Bad magic number in super-block while trying to open /dev/mapper/volgrp1-vm1_hd1

So, I needed a tool which provides access to the partitions of a KVM raw device with some disk image on it.

kpartx to access partitions on KVM raw devices

The easiest way to access a raw device from the KVM host is to use “kpartx”. For Opensuse a relatively up to date RPM is provided in the Update repository “http://download.opensuse.org/update/13.1/“.

For the usage of kpartx see :
KVM-Host – Mounten “virtueller” Gast-Partitionen aus logischen LVM-Volumes
http://linux.die.net/man/8/kpartx
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Virtualization/sect-Virtualization-Troubleshooting_Xen-Accessing_data_on_guest_disk_image.html

Before you apply kpartx you should have a look at “/proc/partitions/” to be able to distinguish the newly attached virtual partitions later on. In my case I get something like:

kvm-host:~ # cat /proc/partitions           
major minor  #blocks  name

   8        0 3906228224 sda
   8        1    2088450 sda1
   8        2  104856576 sda2
   8        3  125829112 sda3
   8        4  125837312 sda4
   8        5  104855552 sda5
   8        6  104856576 sda6
   8        7    2096128 sda7
   8        8  629145600 sda8
   8        9  419433472 sda9
   8       10  146809856 sda10
  11        0    1048575 sr0
 253        0  125829120 dm-0
 253        1   62914560 dm-1
 253        2   62914560 dm-2
 253        3   83886080 dm-3
 253        4   41943040 dm-4
 253        5  104857600 dm-5
 253        6  188743680 dm-6
 253        7  104857600 dm-7
  43        0   62914560 nbd0

Now, we first make sure that the KVM guests supposed to use your raw image devices are offline. More precisely: … that any KVM guests using image partitions on the raw device you want to access by kpartx are offline. I avoid sharing or NFS-, SMB-mounting
partitions on raw devices – then it is clear which KVM guests to stop.

To get access to the partitions of a raw device we use kpartx with the option “-a”. In the following example this is shown for for two raw devices used by two different virtual servers:

kvm-host:~ # kpartx -a /dev/volgrpk/vm1_hd1 
kvm-host:~ # kpartx -a /dev/volgrpk/vm2_hd1 
kvm-host:~ # cat /proc/partitions
major minor  #blocks  name

   8        0 3906228224 sda
   8        1    2088450 sda1
   8        2  104856576 sda2
   8        3  125829112 sda3
   8        4  125837312 sda4
   8        5  104855552 sda5
   8        6  104856576 sda6
   8        7    2096128 sda7
   8        8  629145600 sda8
   8        9  419433472 sda9
   8       10  146809856 sda10
  11        0    1048575 sr0
 253        0  125829120 dm-0
 253        1   62914560 dm-1
 253        2   62914560 dm-2
 253        3   83886080 dm-3
 253        4   41943040 dm-4
 253        5  104857600 dm-5
 253        6  188743680 dm-6
 253        7  104857600 dm-7
  43        0   62914560 nbd0
 253        8    2095104 dm-8
 253        9   60818432 dm-9
 253       10    2095104 dm-10
 253       11   60818432 dm-11
kvm-host:~ # file -s /dev/dm-8
/dev/dm-8: Linux/i386 swap file (new style), version 1 (4K pages), size 523775 pages, no label, UUID=23b50bc8-dbeb-4b2d-be10-75b9f390377e
kvm-host:~ # file -s /dev/dm-9
/dev/dm-9: DOS/MBR boot sector
kvm-host:~ # file -s /dev/dm-10
/dev/dm-10: Linux/i386 swap file (new style), version 1 (4K pages), size 523775 pages, no label, UUID=83220483-e419-42d8-88b6-e6dfe202aebc
kvm-host:~ # file -s /dev/dm-11
/dev/dm-11: DOS/MBR boot sector; GRand Unified Bootloader, stage1 version 0x3, LBA flag 0x1, 1st sector stage2 0x1448200, GRUB version 0.97
kvm-host:~ #

Clearly four additional partitions dm-8 until dm-11 are recognized. Two of them are SWAP partitions. “/dev/dm-9” and “/dev/dm-11” are data partitions each of which is mounted on “/” on my virtual KVM guest servers.

The dm-9 partition is the relevant one for the planned fsck check, which we now can perform in the usual way:

kvm-host:~ # <strong>fsck -f  /dev/dm-9</strong>
fsck from util-linux 2.23.2
e2fsck 1.42.8 (20-Jun-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/volgrpk-vm1_hd1p2: 444945/3808512 files (0.2% non-contiguous), 14281802/15204352 blocks

By the way: A look into “/dev/mapper” shows the available devices and partitions and their device names automatically provided by kpartx:

kvm-host:~ # ls -l /dev/mapper
total 0
crw------- 1 root root 10, 236 Oct 27 07:46 control
....
....
lrwxrwxrwx 1 root root       7 Oct 27 12:09 volgrpk-vm1_hd1 -> ../dm-1
lrwxrwxrwx 1 root root       7 Oct 27 12:10 volgrpk-vm1_hd1_part1 -> ../dm-8
lrwxrwxrwx 1 root root       7 Oct 27 12:21 volgrpk-vm1_hd1_part2 -> ../dm-9
lrwxrwxrwx 1 root root       7 Oct 27 12:10 volgrpk-vm1_hd1p1 -> ../dm-8
lrwxrwxrwx 1 root root       7 Oct 27 12:21 volgrpk-vm1_hd1p2 -> ../dm-9
lrwxrwxrwx 1 root root       7 Oct 27 08:43 volgrpk-vm2_hd1 -> ../dm-2
lrwxrwxrwx 1 root root       8 Oct 27 12:11 volgrpk-vm2_hd1_part1 -> ../dm-10
lrwxrwxrwx 1 root root       8 Oct 27 12:11 volgrpk-vm2_hd1_part2 -> ../dm-11
lrwxrwxrwx 1 root root       8 Oct 27 12:11 volgrpk-vm2_hd1p1 -> ../dm-10
lrwxrwxrwx 1 root root       8 Oct 27 12:11 volgrpk-vm2_hd1p2 -> ../dm-11
lrwxrwxrwx 1 root root       7 Oct 27 07:46 volgrpk-vm_imap_hd0 -> ../dm-3
lrwxrwxrwx 1 root root       7 Oct 27 07:46 volgrpk-vm_imap_hd1 -> ../dm-4

I omitted some lines and devices in the list
above. The last 2 entries stem from a running virtual IMAP server. Note that one and the same device may be presented with different names. again
Now, we can test our virtual server again by booting it – which in my case worked perfectly …

Before testing the virtual LAMP sever with the repaired file system we should not forget to detach the devices still controlled by kpartx:

kvm-host:~ # kpartx -d /dev/volgrp1/vm1_hd1 
kvm-host:~ # kpartx -d /dev/volgrp1/vm2_hd1

A look into “/dev/mapper” again shows that the raw image disk devices are still shown. However, the partitions have disappeared.

kvm-host:~ # ls -l /dev/mapper 
total 0
crw------- 1 root root 10, 236 Oct 27 07:46 control
lrwxrwxrwx 1 root root       7 Oct 27 13:18 volgrpk-vm1_hd1 -> ../dm-1
lrwxrwxrwx 1 root root       7 Oct 27 08:43 volgrpk-vm2_hd1 -> ../dm-2
lrwxrwxrwx 1 root root       7 Oct 27 07:46 volgrpk-vm_imap_hd0 -> ../dm-3
lrwxrwxrwx 1 root root       7 Oct 27 07:46 volgrpk-vm_imap_hd1 -> ../dm-4 

Now, we can test our virtual server (here vm1) by booting it – which worked perfectly in my case …

Hosted Strato server – backups and chained firewall tunneling via SSH and shell

I administer several Linux web servers for partner and customer companies. Most of these servers are V-servers hosted at the German Telekom daughter Strato.

[I have described some reasonable security measures for a Strato server with Opensuse in some articles in this blog. See e.g.:
Strato-V-Server mit Opensuse 12.3 – IV – SSH Key Authentication
Strato-V-Server mit Opensuse 12.3 – III – Stop SSH Root Login
and previous articles referenced there.]

When you work with a hosted server, of course, you want to perform periodic backups. If you – for whatever reasons – do not want to pay for the backup facilities Strato offers, a backup requires that you transfer data from the remote server into your own company network through (encrypted) SSH tunnels. Depending on your specific situation you may wish to create a complete backup or a backup of selected directories on the server. During the backup you want to preserve user-rights and mode settings.

In addition to the topic of creating tunnels across firewalls, the question arises what Linux tool might be convenient to perform the backup task if you work with a shell based connection only. Therefore, I shall briefly discuss what I normally do to perform a manually controlled backup from a hosted Strato server. You can combine the methods described of course with some scripting. The described firewall tunneling by SSH is independent of a specific provider.

Tunneling firewalls with SSH

We presume that our company network has a DMZ with two firewalls – a perimeter firewall “PFW” protecting the DMZ and its hosts against the Internet and one or several inner firewalls “IFW(s)” separating the DMZ from inner network segments. Creating firewall tunnels on the outer and/or inner side of the DMZ is always a critical issue.

Our own backup server system for customer data – let us call it “bup” – is e.g. located in an inner segment of our network. The perimeter firewall “PFW” to the Internet resides on a router and can be configured to forward external WAN ports to ports of special hosts inside the DMZ. Servers inside an inner network segment are allowed to build up SSH connections to hosts in the DMZ across their “IFW(s)”; however the servers in the DMZ are not allowed to initiate SSH connections to the servers in the inner segments. For security reasons we poll data from the servers in the DMZ; we do not forward or push from the DMZ to inner segments. For our scenaio we assume that there is only one inner segment and that we only have to deal with a single “IFW”.

I personally prefer a 2-step process to get the data from the hosted server to the backup destination server “bup”:

  • Step 1: I open a reverse SSH tunnel from a special host “intmid” in our DMZ to the Strato server on the Internet and transfer the data from the Strato server to “intmid”. There, I first of all scan the backup files for viruses and malware.
  • Step 2: Afterwards I stop the reverse tunnel and disallow any incoming connections to “intmid”. I then open a ssh reverse tunnel from my destination server “bup” to “intmid” across the IFW, transfer the files to “bup” and encapsulate them there in an encrypted container.

Some readers may think a 2 step procedure may be exaggerated. If you prefer direct connections from the hosted Strato server to “bup” inside your network you may

  • either use a chain of two reverse SSH tunnels (one tunnel per firewall)
  • or a combination of port forwarding on the “PFW” with
    a reverse tunnel across the “IFW”

Both solutions provide a complete connection from the Strato server to “bup” passing both firewalls of your DMZ. Below I describe both methods briefly.

In both of the following methods we need a reverse SSH tunnel from the backup destination server “bup” (inner segment) to the DMZ host “intmid”. I.e., we export a SSH port of server “bup” temporarily to the host “intmid” in the DMZ. This you may e.g. achieve by entering the command

ssh -R 19999:localhost:22 ssh_user_on_intmid@intmid

at your prompt on host “bup”. The “-R” option triggers the creation of a “reverse” tunnel. Port 19999 is assumed to be unused on “intmid”; port 22 is your local port on “bup” for the SSH daemon sshd. “ssh_user_on_intmid” represents a user for SSH connections on “intmid” with sufficient privileges.

Note: If you just want to build the tunnel in the background without using a terminal or executing remote commands you may use the following combination of options for SSH (instead of a plain “-R”) : ssh -nNTfR …...
Please see the man pages of ssh. These options may be especially helpful when using scripts. So, a more general form of the command could be

ssh -p<sshd port server> -nNTfR <forwarded port server>:localhost:<sshd port local> <username>@<ip server>

Note 1: If and when you really work with background SSH tunnels: Take care not to forget to stop the processes for the background tunnels at the end of your backup operation! In scripts this requires some “pid” determination operations for the running ssh processes.

Note 2: Depending on your sshd configuration you may need to have root rights to build the tunnel.

You can test your reverse tunnel through the inner firewall “IFW” by entering

ssh -p 19999 userid_on_bup@localhost

at the prompt of the “intmid” host. You will of course be asked for the password of a valid user “userid_on_bup” on server “bup” and should then get a prompt on “bup”.

Method 1: Chaining two reverse tunnels

The hosted Strato server allows for a ssh connection on a specific port as this is your only way to work on it. You can use this SSH-connection to build up a reverse tunnel from your DMZ host “intmid” to the Strato server. I.e., the SSH port of your DMZ host shall be exported e.g. as port 19999 on the hosted Strato server. By issuing the following command on “intmid” we tunnel the perimeter firewall “PFW”:

ssh -R 19999:localhost:19999 strato_user@ip_of_your_Strato-server -p 61111

Note: Here we have assumed that the Strato-Server listens on port 61111 as its configured SSH port. (Normally, I change the standard port 22 to a high port number. See:
Strato-V-Server mit Opensuse 12.3 – II – Installation / SSH-Port ändern)

You will of course have to give the password for your “strato_user” on the hosted Strato server before entering the shell there.

Why did we use port 19999 on the DMZ host “intmid”? Because we want to chain the two tunnels – the one from “bup” to “intmid” in the DMZ across firewall “IFW” and the one from “intmid” to our Strato server on the Internet across firewall “PFW” to get a complete encrypted connection from the Strato server to “bup”. Both tunnels “meet” at port 19999 on host “intmid”.

Now, at the prompt of the Strato server you can test the combined (reverse) SSH tunnels by entering

ssh -p 19999 userid_on_bup@localhost

Note: Do not get confused by “localhost” in the command above. You must provide the password for user “userid_on_bup” on the server “bup” (!) inside our inner network segment. Our connected tunnels end up there!

You then should get a prompt for user “user_id_on_bup” on our server “bup”. Ok, we now can successfully tunnel two firewalls at the same time by making use of 2 chained reverse SSH tunnels!

Method 2: Port forwarding on the perimeter firewall

Port forwarding on the perimeter firewall could be an alternative to chaining two tunnels. Having build our obligatory reverse tunnel from “bup” to “intmid” we could in addition change the behavior of our PFW – provided of course that it is configurable. In my case I can establish port forwarding for incoming connections on an some external (WAN) port from a defined IP address on the Internet to a definable port of any host at the other (DMZ) side of the perimeter firewall. E.g I could forward a connection from the Strato server trying to reach the WAN side of the perimeter firewall on port 19999 to port 19999 on “intmid” in the DMZ.

Note: If you really do something like this on your firewall you have to be careful to restrict the forwarding to a defined server on the Internet and to close this firewall hole again after the backup procedure. [It makes no sense here to give commands or details as the configuration procedure varies with the type of firewall used.]

However, for this approach to work with openSSH you in addition have to set a parameter for your sshd configuration in the file “/etc/ssh/sshd_config” on “intmid”:

GatewayPorts yes

Otherwise external hosts will not be allowed to use the reverse tunnel. This setting is somewhat dangerous and you should not forget to change it back.

In this approach we couple (local) port forwarding on the PFW with a reverse tunnel from “bup” to “intmid”. The result is basically the same as with two chained reverse tunnels. However, you have to modify your commands on the Strato server somewhat to use port 19999 at the WAN side of your “PFW”. To test the forwarding plus reverse tunnel on the Strato server you would enter:

ssh userid_on_bup@ip_address_of_your_routers_WAN_interface -p 19999

You have to provide the IP address of the WAN interface of your router. Depending on your DSL provider this may change on a daily basis. So you have to find out what it presently is – e.g by the admin interface of your PFW (router) or by asking an external service (e.g. curl icanhazip.com).

All in all I regard the second method as more complicated and potentially also more dangerous than method 1 – because you must not forget to change and change back your sshd configuration on the DMZ host “intmid” and also to reset your PFW configuration. Therefore, I shall only follow the first approach below.

Use rsync to perform the backup

As we have successfully build up tunnels across our firewalls one may think of using “scp” to perform a backup of the server directories. Actually this is not a good idea if you want to make backups of all server directories including system directories. The reason is:

“scp” follows all symbolic links! At least on Opensuse systems this may lead to infinite loops for certain directories whilst copying!

Therefore it is better to use “tar” or “rsync”. See: http://stackoverflow.com/questions/11030394/is-it-possible-to-make-scp-ignore-symbolic-links-during-copy

Personally, I find “rsync” most convenient. And you can combine it
quite easily with SSH! To use the ports defined for our method 1 (with the two chained reverse SSH tunnels) the right syntax for making a backup of e.g. the directory “/var” would be

rsync -avz -e ‘ssh -p 19999’ /var userid_on_bup@localhost:/backups/bup_strato/server_name/

This command has to be performed on the Strato server. Again: Do not get confused by “localhost” – that’s how SSH tunneling works! The “-a” option of the rsync command means “archive mode”. This preserves the mode and user settings of all files and directories throughout the data copying and performs recursions. “z” leads to a transfer of compressed data which will save you time. “/backups/bup_strato/server_name/” represents an example directory on server “bup” where you want to place the backup files of your special Strato server. Of course you should replace it by your own path on your backup server.

Note 1: You have to issue this commands as root on your Strato server to get access to all of the directories there.
Note 2: Please, note that slash “/” at the end of the directory path on the destination system! And note the missing “/” after the local directory “/var”.
Note 3: Please, note the masking of ssh -p 19999 by single quotation marks! [To specify the port by “-p 19999” at the end of the ssh command would not work as you would mix rsync and ssh parameters].
Note 4: The big advantage of rsync naturally is that you only would exchange changed files at the next backup.

Have much fun now with your Strato server and making backups through SSH tunnels!

Lohnt sich eine COBIT 5 Foundation Zertifizierung für Linuxer?

Linux ist heute im Serverbereich vielfach eine etablierte Größe. Dennoch mag es immer noch viele Projekte geben – im Besonderen im deutschen Mittelstand und/oder der öffentlichen Verwaltung – mit denen die Einführung von Linux-Systemen (z.B. aus Gründen von Kostensenkung) erstmalig angegangen wird. Vielleicht mag im einen oder anderen Fall sogar auch der Desktop betroffen sein (s. z.B. das (noch) laufende Limux-Projekt der Stadt München).

Im Zusammenhang mit Linux-Einführungen ist in einem ersten Schritt viel Überzeugungsarbeit zu leisten, bevor entsprechende strategische Entscheidungen getroffen werden. Hierbei sind klassische Themenfelder der IT-Governance betroffen und die Abstimmung mit einem verantwortlichen CIO kommt mit hoher Wahrscheinlichkeit auf die Tagesordnung. Und dann berührt die Welt der betrieblichen IT-Governance direkt diejenigen interner und externer Mitarbeiter wie Berater.

Ich habe letzte Woche die COBIT 5 Foundation Zertifizierung hinter mich gebracht. COBIT 5 ist ein Framework für die Governance und das Management von Unternehmens-IT. Da ich bereits über ein Spektrum personenbezogener Zertifikate im ITSM-, ISM-, Risk Management- und ITIL-Bereich verfüge, habe ich mich selbst gefragt, ob sich der Aufwand überhaupt lohnt. Nach dem Selbststudium des Buches “Praxiswissen COBIT” und dem Absolvieren eines zugehörigen Kurses meine ich jetzt, dass es gerade für Berater im Linux-Umfeld interessant sein kann, sich mit COBIT auseinanderzusetzen. Hierfür ein paar Gründe:

  • 1) IT-Governance und Linux
    Linux einzuführen und/oder substanziell im Unternehmen auszubauen ist immer auch ein GF- und damit Governance-Thema. Für Berater (ggf. auch technische Berater) und engagierte Mitarbeiter lohnt es sich daher durchaus, ein grundlegendes Verständnis in Bezug auf Governance-Themen – und im Besonderen bzgl. IT-Governance – zu erwerben. Und sei im Fall einer technischen (Führungs-) Kraft auch nur zu dem Zweck, die Motive und Leitlinien im Denken des Managements – im Besonderen eines CIO – besser zu verstehen. Hierfür ist ein 1,5-tägiger Foundation Kurs aus meiner Sicht gut geeignet.
    Gerade technik-begeisterte Verfechter von Linux, die sich von “ideologischen” Motiven manchmal nicht frei machen können oder wollen, mag das Credo der COBIT Zielkaskade – nämlich die Ausrichtung der IT auf die Unterstützung von Unternehmenszielen – helfen, den Entscheidungsträgern die “richtigen” Argumente zu liefern. Eine relevante Frage ist: Kann eine linux-basierte Lösung die Unternehmensziele besser, nachhaltiger und ggf. auch kostengünstiger unterstützen als andere Lösungen? Warum? In welchem Umfang? Wie sehen die zugehörigen Business Cases aus?
    “Open” allein ist auf der Management-Ebene zu wenig …. das ist zwar eine Trivialität, aber COBIT erinnert auch Linux-Anhänger zu Recht und explizit daran, das IT kein Selbstzweck ist. Wir müssen schon aufzeigen, wo, wann und warum genau Linux-basierte Lösungen das Unternehmen die Unternehmensziele effektiver und effizienter erreichen lassen als andere Lösungsansätze. Und wir müssen das auch immer wieder selbstkritisch überprüfen.
  • 2) Projekte / Programme als Teil der IT-Governance
    Wer die ISO 20000 oder die ISO 21000 kennt weiß, dass die Begriffswelten dieser Normen Projekte und deren Prozesse ausklammern. Das ist unter dem Aspekt der Allgemeingültigkeit von Normen verständlich – aber dennoch nicht wirklich praxis- und realitätsnah. Aus einem Anforderungsmanagement heraus entstehen neue Services i.d.R. durch Projekte oder bei großen, strategischen Anliege auch durch Programme. Das gilt natürlich auch und gerade im Linux-Umfeld. Daher ist ein Framework gefragt, welches neben den ITSM-Normen und ITSM, ISM- Best Practices auch auf Best Practices im Bereich des Projektmanagement verweist und entsprechende Prozesse zur Government-Unterstützung einbindet. Dies ist bei CoBIT 5 der Fall.

  • 3) Architektur unter verschiedenen Blickwinkeln
    Linux hat aus meiner Sicht natürlicherweise viel mit dem Aufbau konsistenter, aber auch flexibler und erweiterungsfähiger IT-System- und -SW-Architekturen zu tun. Auch hier gilt: Ein Governance-Framework sollte aus diesem Grund Architektur-Aspekte einbinden. Dies ist bei CoBIT 5 grundsätzlich gegeben, nachdem ein Abgleich mit Togaf stattgefunden hat.
  • 4) Richtlinien
    Ich kenne kaum ein Linux-Projekt und schon gar kein Linux-Einführungs-Projekt, dass nicht der Unterstützung durch das Management bedurft hätte. Damit sind Policies und Richtlinien gefragt. Wer sich mit dieser Thematik noch nicht im Rahmen von anderen Management-Systemen befasst hat, erhält über einen COBIT Foundation Kurs einen guten Einstieg.
  • 5) Breites, umfassendes Alignment mit anderen Frameworks
    COBIT 5 stellt aus meiner jetzigen Sicht ein sehr breit angelegtes Rahmenwerk dar, das gezielt mit anderen wichtigen Frameworks und Normen wie u.a. ITIL V3, ISO 20000, ISO 21000, ISO 31000, ISO 38500, COSO, Togaf abgeglichen wurde. Hier ist seit COBIT 4 eine große Fleißarbeit geleistet worden, die den gesamten Governance-Ansatz auf eine deutlich breitere, umfassendere Grundlage stellt als manche andere mir bekannten Frameworks oder Normen. Nach meiner Einschätzung hat das letztlich mehr Vor- als Nachteile. Zumindest verdeutlicht COBIT 5, an welchen Punkten IT-Governance auf andere Management-Systeme oder Best Practices zurückgreifen kann und sollte. Wie oben schon angedeutet, ergibt sich hierbei u.a. auch ein Anknüpfungspunkt, um die Prozess-Welten von Projekten/Programmen und des IT-Service-Managements in sinnvoller Weise miteinander zu verzahnen – auch wenn COBIT die konkrete Ausdeutung für mein Gefühl nicht hinreichend vornimmt. Aber das ist auch ein spezieller Aspekt, der mich wegen meiner Affinität zu SW-Projekten besonders interessiert.

Natürlich kann ein Foundation Kurs zu den genannten Punkten maximal Grundlagen vermitteln und Hinweise darauf geben, wie entsprechende Prozesse in ein governance-getriebenes Prozessmodell integriert werden können. Das ist aus meiner Sicht jedoch schon interessant genug – auch wenn die Untergliederung von Prozessen in sog. “Praktiken” für den ITILianer etwas gewöhnungsbedürftig ist. Zudem finde ich, dass COBIT aus Sicht des Managements eine ebenso gute Motivation für die Bschäftigung mit weiterführenden oder spezialisierten IT-bezogene Management-Frameworks und Normen bietet wie ITIL dies aus einer ganz anderen Perspektive auch tut.

Den Aufwand für die internationale, personenbezogene Foundation Zertifizierung möchte persönlich ich im Vergleich mit anderen Zertifizierungsprüfungen als wirklich überschaubar einstufen. Das von mir gewählte Buch “Praxiswissen COBIT” ist als Referenz und für ein Selbststudium sicher gut geeignet – auch wenn man nach dem Lesen nicht unbedingt einschätzen kann, was für eine Foundation Prüfung relevant ist. Der Verfasser Markus Gaulke sollte in künftigen Auflagen vielleicht zu Beginn des Buches entsprechende Lesehinweise geben und nicht erst auf S. 363. Die relevanten Kapitel kann man an einem längeren Wochenende gut durcharbeiten. Den Besuch eines ca. 1,5 tägigen Kurses zur Vorbereitung auf die Prüfung empfand ich auf dieser Grundlage als sehr hilfreich, wenn auch nicht zwingend erforderlich. Der von mir besuchte Kurs beim mITSM war erfrischend lebendig und rückte zudem die eine oder andere vorschnell auf der Basis anderer Frameworks oder Normen gefasste Überzeugung gerade. Ein Kurs hilft ferner auch, die oft etwas verquere Fragestellungen, den Stil sowie Haken und Ösen der Prüfungen besser einzuschätzen – zumal mir nach der Prüfung manche Frage zu wortwörtlich aus dem Englischen übersetzt erscheint.

Eine Warnung noch : IT-Governance ist kein Thema für Technik-Freaks – es geht vielmehr
um die Steuerung von Prozessen zur Erreichung von Unternehmens- oder Organisationszielen. Natürlich wird dabei auch die Organisation technischer Aufgabenstellungen berührt. Aber technologische Fragen sind kein primäres Thema eines COBIT-Foundation Kurses – wenngleich sich manches Steuerungselement an konkreten Beispielen gut verdeutlichen lässt.

Aber niemand hat ja festgelegt, dass nicht auch technik-affine Mitarbeiter und Führungskräfte über ihren Tellerrand hinausblicken dürfen. Und eine stringente IT-Governance ist bei den vielfältigen, heterogenen und offenen Angeboten an potentiellen linux-basierten Lösungen für Aufgabenstellungen eines modernen Unternehmens sicher ein essentieller Faktor, durch den die ungeheure Dynamik von Open Source Entwicklungen erst zum Vorteil von Unternehmen besser genutzt und auf priorisierte Ziele hin ausgerichtet werden kann. Führung, Agilität und Prinzipien einer kreativen Selbstorganisation sind für mich überhaupt keine Widersprüche sondern einander ergänzende Faktoren – gerade im Open Source Umfeld. COBIT kann der Unternehmensführung wie dem IT-Management helfen, wirksame Leitplanken für die fruchtbare Entfaltung von Agilität und Dynamik zu setzen.

Character sets and Ajax, PHP, JSON – decode/encode your strings properly!

Ajax and PHP programs run in a more or less complex environment. Very often you want to transfer data from a browser client via Ajax to a PHP server and save them after some manipulation into a MariaDB or MySQL database. As you use Ajax you expect some asynchronous response sent from the PHP sever back at the client. This answer can have a complicated structure and may contain a combination of data from different sources – e.g. the database or from your PHP programs.

If and when all components and interfaces [web pages, Ajax-programs, the web server, files, PHP programs, PHP/MySQL interfaces, MySQL …) are set up for a UTF-8 character encoding you probably will not experience any problems regarding the transfer of POST data to a PHP server by Ajax and further on into a MySQL database via a suitable PHP/MySQL interface. The same would be true for the Ajax response. In this article I shall assume that the Ajax response is expected as a JSON object, which we prepare by using the function json_encode() on the PHP side.

Due to provider restrictions or customer requirements you may not always find such an ideal “utf-8 only” situation where you can control all components. Instead, you may be forced to combine your PHP classes and methods with programs others have developed. E.g., your classes may be included into programs of others. And what you have to or should do with the Ajax data may depend on settings others have already performed in classes which are beyond your control. A simple example where a lack of communication may lead to trouble is the following:

You may find situations where the data transfer from the server side PHP-programs into a MySQL database is pre-configured by a (foreign) class controlling the PHP/MySQL interface for a western character set iso-8859-1 instead of utf-8. Related settings of the MySQL system (SET NAMES) affect the PHP mysql, mysqli and pdo_mysql interfaces for the control program. In such situations the following statement would hold :

If your own classes and methods do not provide data encoded with the expected character set at your PHP/MySQL interface, you may get garbage inside the database. This may in particular lead to classical "Umlaut"-problems for German, French and other languages.

So, as a PHP developer you are prepared to decode the POST or GET data strings of an Ajax request properly before transferring such string data to the database! However, what one sometimes may forget is the following:

You have to encode all data contributing to your Ajax response – which you may deliver in a JSON format to your browser – properly, too. And this encoding may depend on the respective data source or its interface to PHP.

And even worse: For one Ajax request the response data may be fetched from multiple sources – each encoded for a different charset. In case you want to use the JSON format for the response data you probably use the json_encode() function. But this function may react allergic to an offered combination of strings encoded in different charsets! So, a proper and suitable encoding of string data from different sources should be performed before starting the json_encode()-process in your PHP-program ! This requires a complete knowledge and control over the encoding of data from all sources that contribute strings to an Ajax response !

Otherwise, you may never get any (reasonable) result data back to your javascript function handling the Ajax response data. This happened to me lately, when I deployed classes which worked perfectly in a UTF-8 environment on a French LAMP system where the PHP/MySQL interfaces were set up for a latin-1 character set (corresponding to iso-8859-1). Due to proper decoding on the server side Ajax data went correctly into a database –
however, the expected complex response data comprising database data, data from files and programs were not generated at all or incorrectly.

As I found it somewhat difficult to analyze what happened, I provide a short overview over some important steps for such Ajax situations below.

Setting a character set for the PHP/MySQL interface(s)

The character code setting for the PHP/MySQL-connections is performed from the PHP side by issuing a SQL command. For the old interface mysql-interface, e.g., this may look like

$sql_unames = “SET NAMES ‘latin1′”;
mysql_query($sql_unames, $this->db);

Note that this setting for the PHP/MySQL-interfaces has nothing to do with the MySQL character settings for the base, a specific table or a table row! The NAMES settings actually prepares the database for the character set of incoming and outgoing data streams. The transformation of string data to (or from) the character code defined in your database/tables/columns is additionally and internally done inside the MySQL RDBMS.

With such a PHP/MySQL setting you may arrive at situations like the one displayed in the following drawing:

ajax_encoding

In the case sketched above I expect the result data to come back to the server in a JSON format.

Looking at the transfer processes, one of the first questions is: How does or should the Ajax transfer to the server for POST data work with respect to character sets ?

Transfer POST data of Ajax-requests encoded with UTF-8

Normally, when you transfer data for a web form to a server you have to choose between the GET or the POST mechanism. This, of course, is also true for Ajax controlled data transfers. Before starting an Ajax request you have to set up the Ajax environment and objects in your Javascript programs accordingly. But potentially there are more things to configure. Via e.g. jQuery you may define an option regarding the so called “ContentType” for the character encoding of the transfer data, the “type” of the data to be sent to the server and the “dataType” for the structural format of the response data:

$.ajaxSetup( { …..
    ContentType : ‘application/x-www-form-urlencoded; charset=UTF-8’
    type : ‘POST’
    dataType : ‘json’
…});

With the first option you could at least in principle change the charset for the encoding to iso-8859-1. However, I normally refrain from doing so, because it is not compliant with W3C-requirements. The jQuery/Ajax documentation says:

" The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding."
(See: http://api.jquery.com/jquery.ajax/).

Therefore, I use the standard and send POST data in Ajax-requests utf-8 encoded. In our scenario this setting would lead to dramatic consequences on the PHP/MySQL side if you did not properly decode the sent data on the server before saving them into the database.

In case you have used the “SET NAMES” SQL command to activate a latin-1 encoded database connection, you must apply the function utf8_decode() to utf-8 encoded strings in the $_POST-array before you want to save these strings in some database table-
fields!

In case you want to deploy Ajax and PHP codes in an international environment where “SET NAMES” may vary from server to server it is wise to analyze your PHP/MySQL interface settings before deciding whether and how to decode. Therefore, the PHP/MySQL interface settings should be available information for your PHP methods dealing with Ajax data.

Note, that the function utf8_decode() decodes to the iso-8859-1-charset, only. For some cases this may not be sufficient (think of the €-sign !). Then the more general function iconv() is your friend on the PHP side.
See: http://de1.php.net/manual/de/function.iconv.php.

Now, you may think we have gained what we wanted for the “Ajax to database” transfer. Not quite:

The strings you eventually want to save in the database may be composed of substrings coming from different sources – not only from the $_POST array after an Ajax request. So, you need to control where from and in which charset the strings you compose come from. A very simple source is the program itself – but the program files (and/or includes) may have another charset than the $-POST-data! So, the individual strings may require a different de- or en-coding treatment! For that purpose the general “Multibyte String Functions” of PHP may be of help for testing or creating specific encodings. See e.g.: http://php.net/manual/de/function.mb-detect-encoding.php

Do not forget to encode Ajax response data properly!

An Ajax request is answered asynchronously. I often use the JSON format for the response from the server to the browser. It is easy to handle and well suited for Javascript. On the PHP the json_encode() function helps to create the required JSON object from the components of an array. However, the strings combined into a JSON conform Ajax data response object may come from different sources. In my scenario I had to combine data defined

  • in data files,
  • in PHP class definition files,
  • in a MySQL database.

All of these sources may provide the data with a different character encoding. In the most simple case, think about a combination (inclusion) of PHP files which some other developers have encoded in UTF-8 whereas your own files are encoded in iso-8859-1. This may e.g. be due to different standard settings in the Eclipse environments the programmers use.

Or let’s take another more realistic example fitting our scenario above:
Assume you have to work with some strings which contain a German “umlaut” as “ü”, “ö”, “ä” or “ß”. E.g., in your $_POST-array you may have received (via Ajax) some string “München” in W3C compliant UTF-8 format. Now, due to database requirements discussed above you convert the “München” string in $_POST[‘muc’] with

$str_x = utf8_decode($_POST[‘muc’]);

to iso-8859-1 before saving it into the database. Then the correct characters would appear in your database table (a fact which you could check by phpMyAdmin).

However, in some other parts of your your UTF-8 encoded PHP(5) program file (or in included files) you (or some other contributing programmers) may have defined a string variable $str_x that eventually also shall contribute to a JSON formatted Ajax response:

$str_y = “München”;

Sooner or later, you prepare your Ajax response – maybe by something like :

$ay_ajax_response[‘x’] = $str_x;
$ay_ajax_response[‘y’] = $str_y;
$ajax_response = json_encode($ay_ajax_response);
echo $ajax_response;

n
(Of course I oversimplify; you would not use global data but much more sophisticated things … ). In such a situation you may never see your expected response values correctly. Depending on your concrete setup of the Ajax connection in your client Javascript/jQuery program you may not even get anything on the client side. Why? Because the PHP function json_encode() will return “false” ! Reason:

json_encode() expects all input strings to be utf-8 encoded !

But this is not the case for your decoded $str_x in our example! Now, think of string data coming from the database in our scenario:

For the same reason, weird things would also happen if you just retrieved some data from a database without thinking about the encoding of the PHP/MySQL interface. If you had used “SET NAMES” to set the PHP/MySQL interface to latin-1, then retrieved some string data from the base and injected them directly – i.e. without a transformation to utf-8 by utf8_encode() – into your Ajax response you would run into the same trouble as described in the example above. Therefore:

Before using json_encode() make sure that all strings in your input array – from whichever source they may come – are properly encoded in UTF-8 ! Watch out for specific settings for the database connection which may have been set by database handling objects. If your original strings coming from the database are encoded in iso-8859-1 you can use the PHP function ut8_encode() to get proper UTF-8 strings!

Some rules

The scenario and examples discussed above illustrate several important points when working with several sources that may use different charsets. I try to summarize these points as rules :

  • All program files should be written using the same character set encoding. (This rule seems natural but is not always guaranteed if the results of different developer groups have to be combined)
  • You should write your program statements such that you do not rely on some assumed charsets. Investigate the strings you deal with – e.g. with the PHP multibyte string functions “mb_….()” and test them for their (probable) charset.
  • When you actively use “SET NAMES” from your PHP code you should always make this information (i.e. the character code choice) available to the Ajax handling methods of your PHP objects dealing with the Ajax interface. This information is e.g. required to transform the POST input string data of Ajax requests into the right charset expected by your PHP/MySQL-interface.
  • In case of composing strings from different sources align the character enprintcoding over all sources. Relevant sources with different charsets may e.g. be: data files, data bases, POST/GET data, ..
  • In case you have used “SET NAMES” to use some specific character set for your MySQL database connection do not forget to decode properly before saving into the database and to encode data fetched from the base properly into utf-8 if these data shall be part of the Ajax response. Relevant functions for utf-8/iso-8859-1 transformations may be utf8_encode(), utf8_decode and for more general cases iconv().
  • If you use strings in your program that are encoded in some other charset than utf-8, but which shall contribute to your JSON formatted Ajax response, encode all these strings in utf-8 before you apply json_encode() ! Verify that all strings are in UTF8 format before using json_encode().
  • Always check the return value of json_encode() and react properly by something like
    if (json_encode($…) === false
    ) {
    …. error handling code …
    }
  • Last but not least: When designing your classes and methods for the Ajax handling on the PHP side always think about some internal debugging features, because due to restrictions and missing features you may not be able to fully debug variables on the server. You may need extra information in your Ajax response and you may need switches to change from a Ajax controlled situation to a standard synchronous client/server situation where you could directly see echo/print_r – outputs from the server. Take into account that in some situation you may never get the Ajax response to the client …

I hope, these rules may help some people that have to work with jQuery/Ajax, PHP, MySQL and are confronted with more than one character set.