PushOver.net: Scriptgesteuerte Push-Notifications für iOS und Android

Letztens durfte ich einen relativ langwierigen Download via SFTP vornehmen. Da ich allerdings nicht vor dem Rechner sitzen bleiben und auf die Beendigung warten wollte, bin ich immer wieder an den PC gegangen, um den aktuellen Status zu sehen. Dabei kam mir die Idee, dass es doch toll wäre, einen Dienst zu haben, den man per einfacher REST-API ansprechen könnte, um einen Status mitzuteilen. Der Dienst könnte es dann ermöglichen, diesen Status z.B. über einen Browser abzurufen.

@servicecase18 hatte jedoch einen viel tolleren Tipp: Er verwendet für soetwas den Dienst PushOver.net, der im Grunde das macht, was ich möchte - nur besser. Sie bieten ebenfalls eine einfache REST-API an, versenden den Status dann jedoch als Push-Notification an ihre iOS- und Android-App. So hat man den Status direkt auf dem Smartphone. :)

Wenn man sich registriert, erhält der neue Account einen User Key. Nachrichten, die an den User Key geschickt werden, landen auf jedem Gerät, bei dem man mit dem gleichen Account eingeloggt ist. Zudem kann man mit seinem Account auch Applications registrieren, wobei jede Application ein Application Token erhält. Um nun eine Push-Notification zu senden, übergibt man der REST-API mindestens den User Key, den Application Token und die eigentliche Nachricht. Optional gibt es noch weitere Werte, die man setzen kann. Das war's. So einfach.

pushover_appstore pushover_login

PushOver App

Das ganze ist ziemlich praktisch. Zum Beispiel kann man es dazu nutzen, seine Serverüberwachung, die man mit Mercurial implementiert hat, so abzuändern, dass sie nicht einfach nur eine Statusdatei erzeugt, sondern einem stattdessen lieber eine Push-Notification schreibt, wenn sich der Status ändern sollte. So ist man auf der Höhe der Zeit, wenn es darum geht, ein nettes Monitoring zu implementieren. :D

pushover_notification pushover_list

Serverüberwachung mit Push-Notifications

Da ich allerdings nicht die Absicht habe, allen Scripten ein eigenes Application Token zu besorgen - obwohl das möglich wäre - habe ich mir etwas anderes überlegt: Ich hole mir pro Server nur ein Application Token und verwende ein Script, das sich zentral um das Versenden der Push Notifications kümmert. Das hat den zusätzlichen Vorteil, dass nicht jedes kleine Script wissen muss, wie der Versand funktioniert. Stattdessen gibt es einen Ordner, in das ein Script einfach eine Datei ablegt. Der Name der Datei ist der Titel des Push Notification und der Inhalt der Datei ist auch gleichzeitig der Inhalt der Push Notification. :)

Da ich allerdings nicht wollte, dass das Versandscript - "pushinfo.phs" - als Root läuft, habe ich mich dazu entschieden, dass versandte Nachrichten nicht gelöscht werden. Stattdessen wird in einer Statusdatei das letzte Bearbeitungsdatum der Dateien notiert. Sollte sich die Datei ändern (und damit das entsprechende Datum) wird der Inhalt erneut versendet.

Als erstes muss das ganze in der Datei "pushinfo.conf.phs" konfiguriert werden. Der User und die Gruppe, unter denen das Script laufen, heißen bei mir einfach "pushinfo". Der PUSHINFO_PATH muss von dem Nutzer lesbar, der STATUS_PATH zudem auch schreibbar sein. Beim PUSHOVER_APPLICATION_TOKEN und dem PUSHOVER_USER_KEY handelt es sich um die oben beschriebenen Werte von PushOver.net. Mit TITLE_PREPEND kann man dem Titel der Push Notifications statisch noch einen Text voranstellen - das ist praktisch, um z.B. den sendenden Server zu identifizieren. Das ganze ist zudem so konfiguriert, dass Unterstiche im Dateiname durch Leerzeichen ersetzt werden, bevor die Push Notification verschickt wird.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

  # defines the pushover.net API path
 define("PUSHOVER_API_PATH", "https://api.pushover.net/1/messages.json");

  # defines the pushover.net application token
 define("PUSHOVER_APPLICATION_TOKEN", "<REPLACE-ME>");

  #defines the pushover.net user key
 define("PUSHOVER_USER_KEY", "<REPLACE-ME>");

  # defines where the push notifications are located
 # do not forget the trailing slash
 define("PUSHINFO_PATH", "/srv/pushinfo/messages/");

  # defines where the script stores its status
 # do not forget the trailing slash
 define("STATUS_PATH", "/srv/pushinfo/status/");

  # defines which string shall be prepended to the title
 # do not forget some nice separator like a colon and a space
 define("TITLE_PREPEND", "");

  # defines the user the script shall run as
 define("PROCESS_USER", "pushinfo");

  # defines the group the script shall run as
 define("PROCESS_GROUP", "pushinfo");

  # defines the string in the file name that gets
 # replaced by white spaces for the title
 define("REPLACE_FROM_TITLE", "_");

  # defines the string in the file name the
 # REPLACE_FROM_TITLE gets replaced with for the title
 define("REPLACE_TO_TITLE", " ");

  # defines the user agent string for CURL
 define("USER_AGENT", "PushInfo 0.1");

?>

In der Datei "pushinfo.func.phs" ist der eigentliche Code zum Versenden einer Push Notification. Das Tolle daran: Man könnte die Funktionsweise von Pushinfo an dieser Stelle erweitern - z.B. durch den gleichzeitigen Versand von E-Mails. Das aber nur am Rande.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php

  function push_message($title, $message) {
    $result = false;

    // set API values
    $apiHeader = array("title"   => $title,
                       "message" => $message,
                       "token"   => PUSHOVER_APPLICATION_TOKEN,
                       "user"    => PUSHOVER_USER_KEY);

    // configure curl
    $options = array(
      CURLOPT_POST           => true,
      CURLOPT_POSTFIELDS     => $apiHeader,
      CURLOPT_RETURNTRANSFER => true,
      //CURLOPT_SAFE_UPLOAD    => true,
      CURLOPT_USERAGENT      => USER_AGENT,
      CURLOPT_VERBOSE        => 1
    );

    // execute API request
    $curl = curl_init(PUSHOVER_API_PATH);
    curl_setopt_array($curl, $options);
    $output = curl_exec($curl);
    $header = curl_getinfo($curl);
    curl_close($curl);

    // check result
    if (200 === $header["http_code"]) {
      $json = json_decode($output, true);
      if (is_array($json)) {
        if (isset($json["status"])) {
          $result = (1 === $json["status"]);
        }
      }
    }

    return $result;
  }

?>

In der Datei "pushinfo.phs" ist dann die eigentliche Hauptlogik versteckt - das Droppen der Privilegien, das Lesen der Dateien, das Prüfen auf Änderung und das Aufrufen des Notification-Versands und Wegschreiben des Status.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

  require_once(dirname(__FILE__) . "/unchroot.phs");

  require_once(dirname(__FILE__) . "/pushinfo.conf.phs");
  require_once(dirname(__FILE__) . "/pushinfo.func.phs");

  function pushinfo() {
    // first of all drop privileges
    if (force_unroot(PROCESS_USER, PROCESS_GROUP)) {
      // read folder list
      $dir_handle = opendir(PUSHINFO_PATH);
      $files      = array();
      if (false !== $dir_handle) {
        $filename = false;
        do {
          $filename = readdir($dir_handle);

          if (false !== $filename) {
            if (is_file(PUSHINFO_PATH . $filename)) {
              array_push($files, $filename);
            }
          }
        } while (false !== $filename);
      }

      // sort the file array
      sort($files, SORT_STRING | SORT_FLAG_CASE);

      // handle found files
      if (0 < count($files)) {
        for ($index = 0; $index < count($files); $index++) {
          // check if we know the last modification time of this file
          $current_mtime = filemtime(PUSHINFO_PATH . $files[$index]);
          $handle_file   = true;
          if (file_exists(STATUS_PATH . $files[$index])) {
            $last_mtime = file_get_contents(STATUS_PATH . $files[$index]);
            if (false !== $last_mtime) {
              $handle_file = ($current_mtime != $last_mtime);
            }
          }

          // we need to handle this file
          if ($handle_file) {
            // retrieve title and message
            $message = file_get_contents(PUSHINFO_PATH . $files[$index]);
            $title   = TITLE_PREPEND . str_replace(REPLACE_FROM_TITLE, REPLACE_TO_TITLE, $files[$index]);

            // try to push the message
            if (push_message($title, $message)) {
              // save new modification time
              file_put_contents(STATUS_PATH . $files[$index], $current_mtime);
            }
          }
        }
      }
    }
  }

  pushinfo();

?>

Das ganze sollte man nun natürlich regelmäßig ausführen lassen - z.B. per Cron:

1
2
# send pushover.net notifications
*/5 * * * * root php /srv/pushinfo/pushinfo.phs >/dev/null 2>&1

Damit habt ihr alles eingerichtet, was ihr benötigt und könnt wunderschöne neue Spielereien ausprobieren. Noch toller wird es, wenn man das ganze mit einem Monitoring verbindet. So könntet ihr euch z.B. stündlich die neuen, durchschnittlichen Ressourcenauslastungen zuschicken lassen oder euch gar über fehlgeschlagene Loginversuche informieren lassen. :)

Wer übrigens nicht so viel copy&paste betreiben will, kann sich Pushinfo auch über das Mercurial-Repository herunterladen. :)

1
hg clone https://hg.nhg.name/pushinfo/



Drückende Grüße, Kenny

PHP Scripte: Chrooten und Privileges droppen

Derzeit bin ich dabei, meinen eigenen Mailserver aufzusetzen. Eigentlich hatte ich das bereits vor zwei Jahren geplant, doch irgendwie war Google Apps so viel bequemer, als sich selbst um den ganzen Kram zu kümmern - zu Recht: Microsofts Hotmail-Dienst macht wohl öfter mal Probleme, wenn es darum geht, E-Mails zustellen zu dürfen. Was für ein Krampf.

Jedenfalls habe ich mir vorgenommen, entgegen meiner bisherigen Idee auf Google Apps vollständig zu verzichten - sprich deren Mailserver auch nicht als Backup-MX zu verwenden. Das bedingt, dass ich mindestens zwei SMTP-Server für den Empfang von E-Mails betreiben werde. Dazu habe ich mir V-Server bei verschiedenen Betreibern gemietet, die ich - sollte mal etwas sein - einfach um weitere Server erweitern kann. So kann ich sicherstellen, dass ich bei größeren Problemen schnell wieder dazu komme, E-Mails empfangen zu können.

Damit das funktioniert, muss ich die verschiedenen SMTP-Server irgendwie synchronisieren. Da ich als Mailablage Maildir verwende, habe ich mich beim "irgendwie" für SFTP entschieden. Der eine Server verbindet sich zum anderen, prüft dort, ob neue E-Mails vorliegen und spielt sie dann in die lokalen Mailordner ein. Die lokalen Mailordner wiederum gehören jeweils pro Mailaccount einem eigenen Systemnutzer.

Die Synchronisation selbst habe ich in PHP geschrieben - ja, wirklich, in PHP. Da es mir allerdings zu heikel war, die Synchronisation als Root auszuführen, habe ich mir mal angesehen, ob PHP in der Lage ist, innerhalb eines Scripts Privileges zu droppen und sich eventuell sogar Chrooten zu lassen. Und in der Tat, beides ist möglich!

Da ich diese Fähigkeit für sehr sinnvoll halte, habe ich mir das ganze direkt in einer kleinen Bibliothek zusammen gesammelt. Diese enthält zwei wichtige Funktionen "force_chroot()" und "force_unroot()". Sollte ein entsprechender Aufruf fehlschlagen, wird das gesamte Script direkt mit einer Fehlermeldung beendet. Lieber nichts tun, als mit zu vielen Rechten unterwegs sein, war hier meine Devise.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php

  function chroot_normalize_path($path, $trailing_slash = true) {
    $slash     = '/';
    $previous  = '..';
    $empty     = '';
    $current   = '.';
    $backslash = '\\';

    // preset $result
    $result = false;

    // prepare $path as array
    $path = explode($slash, str_replace($backslash, $slash, $path));
    if (0 < count($path)) {
      // prepare $cwd as empty array
      $cwd = array();
      switch ($path[0]) {
        case $empty:
          array_push($cwd, $empty);
          break;

        case $current:
          $cwd = explode($slash, str_replace($backslash, $slash, getcwd()));
          break;

        case $previous:
          $cwd = explode($slash, str_replace($backslash, $slash, getcwd()));
          array_pop($cwd);
          break;

        default:
          $cwd = explode($slash, str_replace($backslash, $slash, getcwd()));
          array_push($cwd, $path[0]);
      }

      // normalize $path
      for ($index = 1; $index < count($path); $index++) {
        switch ($path[$index]) {
          case $empty:
            break;

          case $current:
            break;

          case $previous:
            array_pop($cwd);
            break;

          default:
            array_push($cwd, $path[$index]);
        }
      }

      if ($trailing_slash) {
        if ((1 < count($path)) && ($empty === $path[count($path)-1])) {
          array_push($cwd, $empty);
        }
      }

      $result = implode($slash, $cwd);
    }

    return $result;
  }

  function unroot_get_gid($group) {
    $result = -1;

    if (is_int($group)) {
      $result = $group;
    } else {
      $temp = posix_getgrnam($group);
      if (false !== $temp) {
        $result = $temp["gid"];
      }
    }

    return $result;
  }

  function unroot_get_uid($user) {
    $result = -1;

    if (is_int($user)) {
      $result = $user;
    } else {
      $temp = posix_getpwnam($user);
      if (false !== $temp) {
        $result = $temp["uid"];
      }
    }

    return $result;
  }

  function force_chroot($path) {
    $result = false;

    $path = chroot_normalize_path($path);
    if ((false !== $path) && (is_dir($path))) {
      $result = chroot($path);
    }

    if (false === $result) {
      exit("force chroot failed: path=$path");
    }

    return $result;
  }

  function force_unroot($user, $group) {
    $result = (0 < posix_getuid());

    if (!$result) {
      $groupid = unroot_get_gid($group);
      $userid  = unroot_get_uid($user);

      if ((0 < $groupid) && (0 < $userid)) {
        $result = posix_setgid($groupid);
        if ($result) {
          $result = posix_setuid($userid);
        }
      }
    }

    if (!$result) {
      exit("force unroot failed: user=$user group=$group");
    }

    return $result;
  }

  function force_chroot_unroot($path, $user, $group) {
    $gid = unroot_get_gid($group);
    $uid = unroot_get_uid($user);

    $result = force_chroot($path);
    if ($result) {
      $result = force_unroot($uid, $gid);
    }

    return $result;
  }

?>

Ich habe inzwischen auch schon meine anderen Scripte zumindest mit "force_unroot()" ausgestattet. Ich denke, damit ist bereits einiges an Sicherheit gewonnen - zumindest, wenn man unter Linux arbeitet. ;)

Vielleicht kann ja sonst noch jemand was damit anfangen. :)

Unprivilegierte Grüße, root Kenny

Prüfen, ob ein Prozess gechrootet ist

Heute habe ich nur einen relativ kurzen Tipp, der mir jedoch sehr weitergeholfen hat.

Ich bin derzeit dabei, Dovecot und Postfix einzurichten und sehe mir dabei auch an, wie die einzelnen Teile ordentlich gechrootet werden können. Beim Chrooten läuft man jedoch immer wieder in das Problem, nicht genau zu wissen, ob das, was man da gerade fabriziert hat, wirklich funktioniert.

Wie ich nun lernen durfte, gibt es ein Hilfsmittel, mit denen man die Funktion des Chrootings kontrollieren kann. Gemeint ist der "/proc/" Ordner im System. Dort wird für alle laufenden Prozesse ein Unterordner angelegt, der entsprechend der zugehörigen Prozess-ID benannt ist. Dieser Ordner ist durchaus interessant - so entspricht der Besitzer und die Gruppe des Prozessordners der UID und der GID des Prozesses.

In dem Ordner befinden sich drei Symlinks - "cwd", "exe" und "root" - ersterer zeigt auf das aktuelle Arbeitsverzeichnis des Prozesses, zweiterer zeigt auf den Pfad der ausgeführten Datei und letzerer verweist auf das Verzeichnis, in dem der Prozess gechrootet wurde. Es gibt auch ein paar spannende Textdateien - z.B. "cmdline", "environ" und "maps" - wobei erstere die Aufrufparameter des Prozesses enthält, zweitere die Umgebungsvariablen, mit denen der Prozess arbeitet und letztere sämtliche Libraries, die vom Prozess angebunden sind. Mit den passenden Rechten kann man sich sogar im "./fd/" Unterordner umsehen - dort wird auf alle Dateien verwiesen, die von dem Prozess verwendet werden. :)

Mit diesen Informationen ließe sich lustigerweise ein eigener "ps"-Befehl implementieren.

Wenn man nun also wissen will, ob das eingerichtete Chrooting wirklich funktioniert, kann man sich die notwendige Prozess-ID besorgen und sich anschließend mit folgendem Befehl das Chroot-Verzeichnis anzeigen lassen:

1
sudo ls -la /proc/<Prozess-ID>/root

Praktisch. :)

Gechrootete Grüße, Kenny

Einfache Firewall-Konfiguration mit UFW

Lange Zeit hatte ich mich davor gesträubt - dem Aktivieren einer Firewall auf meinen Servern. Grund war die schiere Angst, mich selbst von den remote administrierten Systemen auszusperren. Geändert habe ich meine Meinung nun durch Finden des Verwaltungstools UFW.

Dabei handelt es sich um die Abkürzung für "Uncomplicated Firewall" und der Name ist Programm. Es handelt sich dabei um eine vereinfachte Verwaltung für iptables-Regeln, die für einfache Fälle jedoch mehr als ausreichen dürfte.

Um sie zu verwenden, muss sie natürlich zuerst installiert werden:

1
sudo apt-get install ufw

Direkt nach dem Installieren sind erstmal keine Regeln aktiviert, sodass man sie in Ruhe konfigurieren kann. Als erstes sollte man definieren, was gilt, wenn keine weiterführenden Regeln definiert sind. Dabei kann man zwischen eingehenden und ausgehenden Verbindungen unterscheiden. Für den Anfang kann man z.B. alle eingehenden Verbindungen verbieten und alle ausgehenden Verbindungen erlauben:

1
2
sudo ufw default deny incoming
sudo ufw default allow outgoing

Als nächstes definiert man dann die einzelnen Ports, die freigegeben werden sollen. Hier müsst ihr aufpassen. Solltet ihr ein System haben, dass ihr remote administrieren könnt, solltet ihr sicher gehen, dass auch der Port freigegeben wird, über den ihr die Administration erreicht (z.B. SSH):

1
2
3
sudo ufw allow in 22
sudo ufw allow in 80
sudo ufw allow in 443

Wenn ihr alle notwendigen Ports freigegeben habt, könnt ihr die Regeln aktivieren:

1
sudo ufw enable

Das war's auch schon! Wenn ihr euch nicht mehr sicher sein solltet, was ihr genau konfiguriert habt, könnt ihr euch einen Status wie folgt beschaffen:

1
sudo ufw status verbose

Die freigegeben Ports sieht man leider erst, wenn die Regeln auch aktiviert wurden. Will man schon vorher mal einen Blick reinwerfen, dann findet man die iptables-Regeln in den Dateien "/lib/ufw/user.rules" (IPv4) und "/lib/ufw/user6.rules" (IPv6).

Mehr Informationen über die Syntax erhaltet ihr in der Ubuntu Community. Alternativ findet man auch im Ubuntu Serverguide einige Hilfestellungen.

Feurige Grüße, Kenny

Windows 10 – Auf zu neuen Geschäftsmodellen?

Gestern wurde nun also Windows 9 Windows 10 vorgestellt - die bisherige Berichterstattung ist eher zurückhaltend und befasst sich primär mit den sichtbaren Änderungen. Leider wird für meinen Geschmack zu wenig auf die Veränderungen im Hintergrund eingegangen. Dabei sind diese eventuell gravierender, als man auf den ersten Blick erkennen mag.

Gehen wir kurz zwei Jahre zurück - damals wurde Windows RT vorgestellt und meine Mutmaßung war, dass Microsoft auf dem Weg sein könnte, eine gemeinsame technische Basis für sämtliche Plattformen - von Smartphones über Tablets bis zu Desktops - zu schaffen. Diese Vermutung wird nun bestätigt. Es soll zukünftig (nach Microsoft) egal sein, welche Plattform man nutzt. Anwendungen sollen einfach plattformübergreifend bereitgestellt werden können.

Es gibt auch andere Änderungen, die Windows 10 zu dem machen, was Windows 8 bereits hätte sein sollen. So hält das Startmenü wieder Einzug, es gibt endlich mehrere virtuelle Desktops, zwischen denen man hin und her wechseln kann und das wohl wichtigste: Desktopnutzern wird nicht mehr die Touchoberfläche aufgezwungen. Stattdessen wird versucht, den Nutzern die User Experience zu bieten, die für jeden jeweiligen Anwendungsfall angemessen ist.

Soweit zu dem, was man an Neuigkeiten sonst lesen kann. Spannend hingegen ist ein Blogeintrag, der kurz nach der Präsentation von Microsoft veröffentlicht wurde. Darin geht es darum, wie Unternehmen zukünftig mit Updates umgehen können. Es ist die Rede davon, dass Endkunden und Businesses, die daran interessiert sind, die "latest innovations" über Windows Updates holen oder einen Gang runter schalten und nur Sicherheitspatches installieren können. Es geht sogar noch weiter:

As mentioned, with Windows 10, we are aiming to reduce the need for the time-consuming and costly wipe-and-reload approach to OS deployment. We know that app compatibility is critical for business. [...] We are creating a streamlined, reliable in-place upgrade process that can be initiated using current management infrastructure.

Das wirft möglicherweise ein neues Licht darauf, wie zukünftig die Weiterentwicklung von Windows aussehen könnte. Bisher war es dort ja eher so, dass man ein Gerät mit einer Version gekauft hat und diese Windows-Version so lange genutzt hat, bis der Rechner veraltet oder defekt war. So wird Windows 7 noch bis Anfang 2020 supportet. Auch der Support für Windows XP endete erst dieses Jahr - nach etwa 13 Jahren. Dementsprechend teuer waren Windows-Lizenzen und dementsprechend außergewöhnlich war es, einen Rechner doch einmal auf eine neue Windows-Version anzuheben.

Innerhalb einer Windows-Version war es eher unüblich, dass komplett neue Features (oder gar "innovations") nachgereicht wurden. Das scheint sich nun mit Windows 10 zu ändern. Damit stellt sich dann allerdings eine neue Frage: Wie will Microsoft zukünftig mit Windows Geld verdienen, wenn Neuerung bald im normalen Update-Prozess nachgereicht werden?

Ein relativ ähnliches Konzept, die Updates samt neuer Features zu verteilen, kennt man von Mac OS X, wo jedes Jahr eine neue Version erscheint, die sich relativ schnell und relativ breitflächig verteilt. Dass man solch kurze Versionssprünge in Betracht ziehen könnte, sieht man meiner Meinung an Windows 8.1 - es ist kein typisches Servicepack, sondern bietet Neuerungen im System, behält jedoch gleichzeitig die Hauptversion bei. Im Gegensatz zu Microsoft wird die Weiterentwicklung des Betriebssystems bei Apple jedoch durch den zugehörigen Hardwarekauf abgegolten. Dieser Finanzierungspfad fehlt Microsoft...

...noch. Microsoft ist Eigentümer der Handysparte von Nokia geworden, kann also zukünftig Smartphone-Hardware und -Software aus einer Hand anbieten. Auch bei den Surface-Tablets sind sie bereits Hardware- und Software-Lieferant. Da Microsoft zudem bei der XBox bereits mehrjährige Erfahrung mit der Entwicklung von desktopähnlicher Hardware hat, halte ich es nicht für ausgeschlossen, dass sie auch den Schritt wagen könnten, ein Microsoft-Notebook auf den Markt zu bringen.

Der von Apple vorgezeigte Weg - Hardware, Betriebssystem, Software und Services zu einem eng verwobenen Ökosystem zu verschmelzen - könnte der Königsweg sein, den Microsoft inzwischen im Auge hat. Und mit einem einheitlichen System, das sich einfach nur auf das jeweilige Gerät optimiert, könnte Microsoft sogar einen Vorteil gegenüber Apple haben, das sein iOS und sein OS X zwar funktional angleicht, diese jedoch weiterhin getrennte Systeme sein lässt - nämlich genau dann, wenn man die von Canonincal beschworene Convergence tatsächlich umsetzen kann.

Wie es auch ausgehen wird, derzeit ist es jedenfalls spannend, zu sehen, wie Microsoft mit Windows weiter vorgehen wird. Mit etwas Intelligenz und guten Konzepten könnte Microsoft es schaffen, seine Marktdominanz in kurzer Zeit stark zu festigen und im Mobilmarkt sogar auszubauen. Die Bausteine sind da, jetzt müssen sie nur noch gut kombiniert werden.

Was denkt ihr von den aktuellen Schritten von Microsoft? Glaubt ihr, dass Microsoft in der Lage sein wird, ein übergreifendes System zu schaffen?

Fensterlose Grüße, Kenny

P.S.: Man könnte natürlich auch einen BWLer eingestellt haben, der die Idee Klasse findet, das Betriebssystem zu einer Software-as-a-Service zu deklarieren und sie im Monatsabo zu vermieten und Nichtzahler mit regelmäßiger Popup-Werbung zu nerven. Hoffen wir mal, dass Microsoft ein wenig intelligenter sein wird. :D

Seite 1 von 82123...Letzte »