#!/bin/bash
# script: run gtk application as another user
# author: bert2002
# notes:
OTHERUSER=peter
if [ -z "$1" ];then
echo "$0 <application>"
exit
fi
COOKIE=$(xauth list | grep $(uname -n) | awk '{print $3}')
sudo su - $OTHERUSER -s /bin/bash -c "unset XAUTHORITY ; touch ~/.Xauthority ; DISPLAY=:0; export DISPLAY ; xauth add :0 . $COOKIE ; $1"
Docker load vs import
Nachdem man einen Docker container exportiert hat kann man diesen mit docker import
oder docker load
importieren. Jedoch funktioniert nur docker load
correct und import
führt zu einem irritierenden Fehler:
$ docker import tools-1597033145.tar.gz tools:latest
sha256:f229b184eb2f0c0f2c59fac86adec2c32ac742a8fc1ea6898f51543dfbf0161b
$ docker run -it tools /bin/bash
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown.
ERRO[0003] error waiting for container: context canceled
Wenn man den Container mit load
importiert, funktioniert es einwandfrei. Ich hatte leider noch keine Zeit den unterschied oder Fehler zu untersuchen, aber es hat etwas mit export/import und save/load zu tun. Export erstellt snapshots und save erstellt einen dump.
Reverse SSH Tunnel mit Autossh
Einen SSH Tunnel kann man für viele nützliche Sachen einsetzen und hilft bei authentification und verification von einer Verbindung.
Im Normalfall verbindet man Server1 mit Server2 und jetzt ist es möglich von Server1 nach Server2 den Tunnel zu benutzen.
Ich hatte jetzt das Problem dass die IP von Server2 sich immer veraendert und es keinen offenen Port auf Server2 gibt. Ich musste jedoch von Server1 auf Server2 zugreifen. Dabei hilft uns ein reverse SSH Tunnel. Der Tunnel wird von Server2 aufgebaut nach Server1, aber ich kann von Server1 auf den Tunnel zugreifen.
Das ist schnell und einfach konfiguriert und ist eine einfach systemd konfiguration nachdem man autossh installiert hat.
Datei: /etc/systemd/system/autossh.service
[Unit]
Description=Opens a ssh tunnel and keeps it open
After=network-online.target
[Service]
# AUTOSSH_GATETIME is used to restart ssh within autossh when a connection failed.
Environment=AUTOSSH_GATETIME=0
User=root
ExecStart=/usr/bin/autossh -N -q -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -p 22 -l $USERNAME -R $REMOTEPORT:localhost:22 $REMOTEHOST
[Install]
WantedBy=multi-user.target
$USERNAME: Der Benutzername mit dem man sich auf Server1 verbinden möchte.
$REMOTEPORT: Der Port auf dem der Tunnel auf Server1 lauschen soll
$REMOTEHOST: Die Adresse von Server1
Am besten tested man die Verbindung manuell einmal, damit man auch den Hostkey verifiziert (ssh pubkey muss vorher ausgetauscht werden) wird, ansonsten kann man den Dienst aktivieren.
systemctl daemon-reload
systemctl start autossh
Gitlab Projects import nach Searchcode
Die Codesuche in Gitlab selber ist etwas beschraenkt und man muss auf Drittanbieter zurueckgreifen. Ich teste momentan Searchcode. Die Community version is kostenlos und fuer etwas Geld bekommt man mehr funktionen.
Das Problem ist jedoch das man jedes git repository einzeln hinzufuegen muss. Zum Glueck gibt es eine API die das einem abnehmen kann. Dabei exportieren wir die List aus Gitlab und importieren diese automatisch nach Searchcode.
Zum Glueck kann man mit ssh keys arbeiten, jedoch muss man dafuer die Config anpassen.
Datei: ~/.ssh/config
Host gitlab.example.com
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
Anschliessen muss man folgendes Script anpassen und auf dem Server wo Searchcode laeuft ausfuehren.
#!/usr/bin/python
# script: import gitlab projects into searchcode
# author: bert2002
# notes:
import sys
import os
import json
import urllib2
from hashlib import sha1
from hmac import new as hmac
import urllib2
import json
import urllib
import pprint
import time
# Gitlab Settings
TOKEN = 'SECRET_ACCESS_TOKEN'
GITLAB = 'https://gitlab.example.com/api/v4/'
# Searchcode Settings
publickey = "SECRET_PUBLICKEY"
privatekey = "SECRET_PRIVATEKEY"
print "checking jobs in gitlab"
req = urllib2.Request(GITLAB + 'projects?page=1&per_page=100')
req.add_header('Content-Type', 'application/json')
req.add_header('PRIVATE-TOKEN', TOKEN)
data = json.load(urllib2.urlopen(req))
for project in data:
job_id = project['id']
ssh_url_to_repo = project['ssh_url_to_repo']
name_with_namespace = project['name_with_namespace']
path_with_namespace = project['path_with_namespace']
web_url = project['web_url']
archived = project['archived']
print("Repository: %s Archived: %s" % (name_with_namespace,archived))
reponame = name_with_namespace
repourl = ssh_url_to_repo
repotype = "git"
repousername = ""
repopassword = ""
reposource = web_url
repobranch = "master"
message = "pub=%s&reponame=%s&repourl=%s&repotype=%s&repousername=%s&repopassword=%s&reposource=%s&repobranch=%s" % (
urllib.quote_plus(publickey),
urllib.quote_plus(reponame),
urllib.quote_plus(repourl),
urllib.quote_plus(repotype),
urllib.quote_plus(repousername),
urllib.quote_plus(repopassword),
urllib.quote_plus(reposource),
urllib.quote_plus(repobranch)
)
sig = hmac(privatekey, message, sha1).hexdigest()
url = "http://localhost:8080/api/repo/add/?sig=%s&%s" % (urllib.quote_plus(sig), message)
data = urllib2.urlopen(url)
data = data.read()
data = json.loads(data)
print data['sucessful'], data['message']
sig = hmac(privatekey, message, sha1).hexdigest()
url = "http://localhost:8080/api/repo/reindex/?sig=%s&%s" % (urllib.quote_plus(sig), message)
data = urllib2.urlopen(url)
data = data.read()
time.sleep(1)
ESP8266 + OLED Display shows PagerDuty incidents
Seit ein paar Tagen spiele ich mit dem ESP8266 Chip herum. Das ist ein Arduino fähiger Chip mit Wifi. Die Entwicklerboards gibt es schon für knapp 8EUR in Deutschland und sind überraschend leistungsfähig.
Ich hatte vorher noch nie etwas mit Arduino gemacht, aber dank der vielen verfügbaren Libraries hat man sehr schnell Erfolg mit kleinen Projekten. So habe ich noch ein kleines Display angeschlossen und dieses zeigt mir die offenen incidents bei PagerDuty an. Super schnell und lustig.
Den Code gibt es auf github.com und hier ein Beispiel:
ESP8266 + Arduino IDE + MacOSX
Das Internet of Things (IoT) immer mehr in unseren Alltag Einfluss nimmt, ist vermutlich jedem klar. Ich wollte auch ein bisschen damit herumspielen und bin dabei auf den Chip ESP8266 gestoßen. Der kleine Chip hat WLAN, verbraucht wenig Strom und kann mittels LUA oder Arduino IDE programmiert werden.
Unter Linux ging das alles sehr schnell und nachdem man die Arduine IDE und das Board Packet installiert hat, kann man direkt loslegen. Unter MacOSX Sierra hatte ich jedoch Probleme dass das Board in der Arduino IDE erkannt wird. Erst nach langem recherchieren bin ich auf einen Treiber gestoßen der funktioniert.
Den Treiber und mehr gibt es auf kig.re.
Monero Mining on Ubuntu 16.04
Account:
Der einfachste Weg einen Account zu erstellen ist auf mymonero.com. Man muss sich um keine Blockchain kümmern und es ist komplett Anonym. Auf der Seite bekommt man auch seine WalletID die wir bei dem Miner mit angeben müssen. Diese müsst Ihr bei $WALLETID ersetzen. Als Mining Pool nehmen wir monerohash.com.
Installation:
apt update
apt install libcurl4-openssl-dev libncurses5-dev pkg-config automake yasm
sysctl -w vm.nr_hugepages=48 # three times more then your cpu cores
cd /opt/
git clone https://github.com/wolf9466/cpuminer-multi
cd cpuminer-multi
./autogen.sh
CFLAGS="-march=native" ./configure
make
Start:
/opt/cpuminer-multi/minerd -a cryptonight -o stratum+tcp://monerohash.com:3333/
-u $WALLETID -p $RANDOM
Reporting:
Falls man mehrere Instanzen am laufen hat, will man diese auch ein bisschen überwachen bzw. wissen was läuft. Dafür habe ich einen kleinen Bot geschrieben der mit der Monerohash IP sich die aktuellen Daten zieht und diese mir in einem Slack Channel sendet. Das ganze gibt es auf github.com.
BlaBlaDNS – Ein Kostenloser DynDNS Anbieter
NOTE: BlaBlaDNS ist jetzt bekannt als TokenDNS.
Ich darf mit Freude verkünden das endlich mein neustes Projekt online gegangen ist. Ein kleiner, aber feiner Dynamic DNS Dienst der natürlich kostenlos ist. Getauft ist das Projekt auf BlaBlaDNS und kann unter www.blabladns.co erreicht werden.
Es gibt schon unzählige DDNS Dienste, aber leider keiner der mir alle Features bot die ich haben wollte. Er sollte sicher sein, schöne API und ich wollte auch IPv6 Rekords sowie die TTL bestimmen können. Konnte ich nicht finden und so musste ich mir einen bauen.
Momentan muss man die API unbedingt benutzen, weil das Webinterface noch keinen Schreibzugriff auf die API hat, aber das wird sich bald ändern.
Wie kann ich also BlaBlaDNS benutzen?
Als erstes muss man sich sicher anmelden und wenn man den API Key hat kann man direkt los legen. Den rest kann man einfach per API machen. Beispiele existieren momentan für curl, aber die Dokumentation wird noch erweitert.
Kleines Beispiel um die Subdomain www5.blabladns.xyz zu registrieren und aktualisieren.
Subdomain Registrieren
curl --get "https://api.blabladns.co/v1/reserve" \
-d apikey=${apikey} \
-d name=www5
Rekord Aktualisieren
curl --get "https://api.blabladns.co/v1/update" \
-d apikey=${apikey} \
-d name=www5 \
-d content=$(curl -4 ifconfig.co)
Status
curl --get "https://api.blabladns.co/v1/reserve" \
-d apikey=${apikey} \
-d name=www5
Rekord automatisch mit cron aktualisieren
echo "0 * * * * root curl -s --get https://api.blabladns.co/v1/update -d apikey=${apikey} -d name=www5 -d content=$(curl -s -4 ifconfig.co) >/dev/null" > /etc/cron.d/blabladns
Die Features und Möglichkeiten werden in nächster Zeit noch weiter wachsen und wer die Entwicklung weiter verfolgen möchte sollte dem Blog von BlaBlaDNS folgen.
Wünsche? Anregungen? Features? Gerne baue ich die in den Dienst ein! Einfach Melden!
Chef + Ruby Integration
Auch wenn Chef Ruby einsetzt unterstützt es leider doch nicht alles. Ich wollte eine nette Regex direkt im Cookbook ausführen lassen. In Ruby wunderbar funktioniert, beim Chef run wurde die Regex nicht korrekt ausgeführt. Ich habe sogar zwei verschiedene ausprobiert (wobei die erste nicht ganz korrekt ist, aber auch funktioniert), aber leider Erfolglos. sed funktioniert eben einfach immer :)
Regex: Kommentiere eine Zeile, wenn ubuntu.com oder canonical.com enthalten ist und nicht mit einer Raute anfängt.
ruby_block 'modify /etc/apt/sources.list' do
block do
File.write( f = "/etc/apt/sources.list",
#File.read(f).gsub(/(?!^#)(.*)(?:ubuntu\.com|canonical\.com)(.*)/) { "# #{$&}" }
File.read(f).gsub(/^[^!#]*(?:ubuntu\.com|canonical\.com)/m) { "# #{$&}" }
)
end
end
Lösung:
execute 'modify /etc/apt/sources.list with sed' do
command "sed -i -e '/ubuntu\.com/s/^#*/#/' -e '/canonical\.com/s/^#*/#/' /etc/apt/sources.list"
end
Cloudera Manager und Grafana
In dem Cloudera Manager kann man sich schon verschiedene Grafen der einzelnen Komponenten anschauen, wenn man jedoch auch Grafana benutzt will man nicht wirklich immer umschalten.
Es ist jedoch möglich ein Plugin für Grafana zu schreiben um die Daten direkt aus dem CDH zu ziehen. Amir Pakdel hatte ein Plugin für Grafana 1.x geschrieben, welches ich für Grafana 2.x umgeschrieben habe.
Download: Grafana CDH Datasource Plugin
Installation
Damit wir in kein Problem mit XSS kommen müssen wir unsere anfragen an das CDH mit einem kleinen Proxy über den Server von Grafana abfertigen. Dafür muss folgende Apache Konfiguration angelegt werden:
ProxyPass http://$CLOUDERAMANAGER:7180/api/v9
ProxyPassReverse http://$CLOUDERAMANAGER:7180/api/v9
RequestHeader set Authorization "Basic <base64>"
Header set Access-Control-Allow-Origin "*"
Das $CLOUDERAMANAGER muss mit dem Hostnamen von dem CDH Manager ersetzt werden und in dem RequestHeader der Benutzername:Passwort (in base64) von dem Benutzer der mit der API von CDH reden darf. Anschließend noch ein paar Module aktivieren:
# a2enconf cdh
# a2enmod proxy_http proxy request headers
# service apache2 restart
Anschließend können wir das Modul installieren und Grafana neu starten. Vor dem Neustart, muss jedoch noch die $GRAFANAURL in der datasource.js angepasst werden.
# tar -xzf cdh.tar.gz -C /usr/share/grafana/public/app/plugins/datasource/ # service grafana-server restart
Jetzt kann man schon beginnen eine neue Datasource zu erstellen und fleißig Graphen bauen. Wie baut man die Graphen? Man muss die SQL Statements aus dem CDH in Grafana übertragen. Die Statements bekommt man aus den vorhanden Graphen:
In dem JSON befindet sich das Query, welches einfach in die Row im Grafana eingetragen werden muss. Fertig.
Owncloud 8.0 Upgrade
Wenn man momentan auf Owncloud 8.0 upgraded erhalten viele Benutzer nur noch eine weiße Seite und nichts passiert. In den Logdateien kann man auch keine Fehler finden.
Das Problem liegt an ein paar Plugins die noch nicht für 8.0 aktualisiert worden. Diese muss man deaktivieren:
# cd /zur/deiner/owncloud
# sudo -u www-data php occ app:disable calendar
# sudo -u www-data php occ app:disable contacts
SSH Tunnel in einer Jail öffnen
Gehen wir mal davon aus das wir einen SSH Benutzer in einer Jail eingesperrt haben. Dieser möchte aber unbedingt einen SSH Tunnel zu einem anderen Server aufbauen. Normalerweise will man das nicht und verbietet dieses in der sshd_config Konfiguration mittels AllowTcpForwarding no.
Ich wollte das trotzdem einmal habe und konnte einfach nicht finden warum es nicht möglich war. Meine Fehlermeldung:
# ssh -N -L 1337:127.0.0.1:3306 user@$remoteserver -vv
debug1: Connection to port 1337 forwarding to 127.0.0.1 port 3306
requested.
debug2: fd 7 setting TCP_NODELAY
debug1: channel 2: new [direct-tcpip]
channel 2: open failed: administratively prohibited: open failed
debug2: channel 2: zombie
debug2: channel 2: garbage collecting
debug1: channel 2: free: direct-tcpip: listening port 1337 for
127.0.0.1 port 3306, connect from ::1 port 58509, nchannels 3
Ein kleiner Test:
# telnet localhost 1337
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
Hat leider nichts geholfen und wenn die Fehlermeldung schon sagt das es $irgendwas nicht öffnen kann, muss man sich das einmal genauer mit strace anschauen:
# strace -p $pid -ff
Process $pid attached - interrupt to quit
select(8, [3 7], [], NULL, NULL) = 1 (in [3])
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
read(3,
"\354O-\1\374O\215\5\4G\323\226\371\207V\325s\37\277-\350\207$)\261}\235\241\320\306\302M"...,
16384) = 96
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4
connect(4, {sa_family=AF_FILE, path="/dev/log"}, 110) = -1 ENOENT (No such file or directory)
close(4) = 0
select(8, [3 7], [3], NULL, NULL) = 1 (out [3])
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
write(3,
"\374\231G-+\2,\365\255\312\240Y\20\217YL\350\3t193O\35\323\224\237\3728\260\233\223"...,
64) = 64
select(8, [3 7], [], NULL, NULL
In der Jail hat kein /dev/log existiert und ohne ein bisschen herumzuloggen möchte SSH anscheinend auch keinen Tunnel aufbauen. Kurzerhand das Device angelegt und schon ging es.
root@server:/var/jail/user/dev# ls -al log
srw-rw-rw- 1 root root 0 Mar 3 16:08 log
root@server:/var/jail/user/dev# grep -E '^\$' /etc/rsyslog.d/jail.conf
$AddUnixListenSocket /var/jail/user/dev/log
root@server:/var/jail/user/dev#