Jan Ulrich Hasecke
2022-07-27 6d1db446926b7825302e39695eed59c596ca3c6f
commit | author | age
261280 1 # HSAdmin über Skripte steuern {#kap-hsscript-skript}
JUH 2
2c93a1 3 Im Abschnitt [Syntax](#kap-hsadmin-syntax) wurde die Option `-f` erwähnt, die gesetzt werden kann, um HSAdmin eine Datei zu übergeben, in der sich die Befehle befinden.
JUH 4 Die Option ermöglicht es, ohne großen Aufwand Skriptdateien zu pflegen, mit denen wiederkehrende Aufgaben bequem erledigt werden können.
5 Dieses Kapitel zeigt, wie Sie die Anlage einer neuen Wordpress-Website mit Hilfe eines solchen Skripts vereinfachen können.
261280 6
2c93a1 7 Bevor Sie die eigentliche Wordpress-Software installiert, müssen mehrere Schritte auf der Hostsharing-Plattform erledigt sein.
261280 8
2c93a1 9 1. Es existiert ein Domain-Admin bzw. es wird ein neuer Domain-Admin angelegt.
JUH 10 2. Es wird eine Domain erstellt und dem Domain-Admin zugewiesen.
11 3. Es wird ein Datenbank-Nutzer angelegt.
12 4. Es wird eine Datenbank angelegt und dem Datenbank-Nutzer zugewiesen.
261280 13
2c93a1 14 Mit der folgenden Skript-Datei kann man diese vier Schritte mit einem Befehl ausführen.
261280 15
2c93a1 16 ```bash
261280 17 user.add ({set:{name:'xyz00-domains',comment:'Domain-Admin',password:'!1?2-3aBc',shell:'/bin/bash'}})
JUH 18 domain.add ({set:{name:'beispiel.de',user:'xyz00-domains'}})
19 mysqluser.add  ({set:{name:'xyz00_owner',password:'?2?3-4cVg'}})
20 mysqldb.add ({set:{name:'xyz00_abc',owner:'xyz00_owner'}})
21 ```
22
2c93a1 23 In Zeile 1 wird der Domain-Admin erzeugt, in Zeile 2 die Domain `beispiel.de` angelegt, in Zeile 3 der Datenbank-Nutzer und in Zeile 4 die Datenbank.
JUH 24 Es ist möglich, die Datei lesbarer zu formatieren, indem man jedem Key-Value-Paar eine eigene Zeile zuweist.
261280 25
2c93a1 26 ```bash
261280 27 user.add ({set:{
JUH 28 name:'xyz00-domains',
29 comment:'Domain-Admin',
30 password:'!1?2-3aBc',
31 shell:'/bin/bash'
32 }})
33 domain.add ({set:{
34 name:'beispiel.de',
35 user:'xyz00-domains'
36 }})
37 mysqluser.add ({set:{
38 name:'xyz00_owner',
39 password:'?2?3-4cVg'
40 }})
41 mysqldb.add ({set:{
42 name:'xyz00_abc',
43 owner:'xyz00_owner'
44 }})
45 ```
46
2c93a1 47 Wenn Sie die Datei unter dem Namen `befehlsskript.txt` im Verzeichnis des `Paket-Admin` speichern, können Sie alle Befehle mit einem HSAdmin-Aufruf abarbeiten:
261280 48
JUH 49 ``` console
50 xyz00@h50:~$ hsscript -f befehlsskript.txt
51 ```
52
2c93a1 53 Wenn Sie beispielsweise häufig Wordpress-Websites installieren, können Sie für jede Website eine solche Befehlsdatei anlegen und unter einem sinnvollen Namen (z.B. `wordpress-beispiel_de.txt`) abspeichern.
261280 54
6d1db4 55 ::: attention
261280 56 Beachten Sie die richtige Reihenfolge
JUH 57
2c93a1 58 Bei der Anlage von Benutzern, Datenbanken und Domains ist die im Beispiel gezeigt Reihenfolge einzuhalten.
JUH 59 Um eine Domain anzulegen, muss der Domain-Admin bereits existieren.
60 Eine Datenbank kann nur erzeugt werden, wenn der Datenbank-Nutzer bereits angelegt ist.
261280 61
2c93a1 62 Beim Löschen müssen Sie die Reihenfolge umkehren: Datenbank löschen, Datenbank-Nutzer löschen, Domain löschen, Domain-Admin löschen.
261280 63 :::
JUH 64
2c93a1 65 Noch bequemer ist es, die notwendigen Benutzer, Domains und Datenbanken mit Hilfe eines ausführlicheren JS-Skripts oder über die Python-API anzulegen.
261280 66
JUH 67 ## HSAdmin mit Javascript ansprechen
68
2c93a1 69 Im Folgenden zeigen wir zwei JS-Skripts, die in der Regel im Verzeichnis des Paket-Admin mit dessen Benutzerrechten aufgerufen werden.
JUH 70 Mit dem ersten Skript erstellen wir eine Domain und weisen ihr einen eigenen Domain-Admin zu, dessen Name aus dem Namen der Domain abgeleitet wird.
71 Mit dem zweiten Skript erzeugen wir eine Datenbank und einen Datenbank-Nutzer, sodass wir unter der gewünschten Domain zum Beispiel eine PHP-Anwendung wie Wordpress einrichten können.
261280 72
JUH 73 ### JS-Skript zur Anlage einer Domain
74
2c93a1 75 Ein Skript, um eine Domain mit einem gesonderten Domain-Admin anzulegen, könnte so aussehen:
261280 76
2c93a1 77 ```bash
JUH 78 #!/usr/local/bin/hsscript -f
261280 79
2c93a1 80 createDomainAndDomainAdmin(arguments);
261280 81
2c93a1 82 function pwGen() {
JUH 83     var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_#%&+!?=";
84     var pwLength = 12;
85     var randomstring = '';
86     for (var i=0; i<pwLength; i++) {
87         var rnum = Math.floor(Math.random() * chars.length);
88         randomstring += chars.substring(rnum,rnum+1);
89     }
90     return randomstring;
91 }
92
93 function createDomainAndDomainAdmin(args) {
94     var domainName = args[0];
95     var userName = 'xyz00-' + args[0].replace("-","_");
96     var randomPassword = pwGen();
97     var createdUser = user.add({set:{name:userName,password:randomPassword,shell:'/bin/bash'}});
98     var createdDomain = domain.add({set:{name:domainName,user:userName}});
99     print("created domain " + createdDomain[0].name + " with domainadmin " + createdUser[0].name + " and password " + randomPassword);
100 }
101 ```
102
103 Die Funktion `pwGen()` erzeugt ein achtstelliges Passwort aus einer Reihe von vorgegebenen Zeichen.
104 Empfehlenswert sind längere Passworte.
105 Die Funktion `createDomainAndDomainAdmin(args)` erzeugt die Domain und den Domain-Admin.
106 Der Namen des Domain-Admin ergibt sich aus dem Namen der Domain.
107 Bei einer Domain, die einen Bindestrich enthält, muss dieser durch einen Unterstrich ersetzt werden, da Benutzernamen nur einen Bindestrich enthalten dürfen.
108
109 Das Skript wird im Benutzerverzeichnis des Paket-Admin gespeichert und ausführbar gemacht:
261280 110
JUH 111 ``` console
112 xyz00@h50:~$ chmod u+x createdomainandadmin.js
113 ```
114
115 Anschließend können Sie es folgendermaßen aufrufen:
116
117 ``` console
118 xyz00@h50:~$ ./createdomainandadmin.js my-domain.de
119 created domain my-domain.de with domainadmin xyz00-my_domain.de and password slo%haY=
120 ```
121
2c93a1 122 Wenn Sie alle Domains mit einem einzigen Domain-Admin verwalten, können Sie den Benutzernamen des Domain-Admin hart kodieren.
261280 123
2c93a1 124 ```bash
JUH 125 #!/usr/local/bin/hsscript -f
126
127 createDomainAndDomainAdmin(arguments);
128
129 function pwGen() {
130        var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_#%&+!?=";
131        var string_length = 12;
132        var randomstring = '';
133        for (var i=0; i<string_length; i++) {
134                   var rnum = Math.floor(Math.random() * chars.length);
135                   randomstring += chars.substring(rnum,rnum+1);
136               }
137        return randomstring;
138 }
139
140 function createDomainAndDomainAdmin(args) {
141        var domainName = args[0];
142        var userName = 'xyz00-doms';
143        var randomPassword = pwGen();
144        var createdUser = user.add({set:{name:userName,password:randomPassword,shell:'/bin/bash'}});
145        var createdDomain = domain.add({set:{name:domainName,user:userName}});
146        print("created domain " + createdDomain[0].name + " with domainadmin " + createdUser[0].name + " and password " + randomPassword);
147
148 ```
261280 149
JUH 150 ### JS-Skript zur Anlage einer Datenbank
151
152 Das Skript zur Anlage einer Datenbank und eines Datenbank-Nutzers sieht
153 ähnlich aus.
154
2c93a1 155 ```bash
JUH 156 #!/usr/local/bin/hsscript -f
261280 157
2c93a1 158 createMySQLUserAndDB(arguments);
261280 159
2c93a1 160 function pwGen() {
JUH 161    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_#%&+!?=";
162    var pwLength = 18;
163    var randomstring = '';
164    for (var i=0; i<pwLength; i++) {
165        var rnum = Math.floor(Math.random() * chars.length);
166        randomstring += chars.substring(rnum,rnum+1);
167    }
168    return randomstring;
169 }
170
171 function createMySQLUserAndDB(args) {
172    var userName = 'xyz00_' + args[0];
173    var dbName = userName;
174    var randomPassword = pwGen();
175    var createdUser = mysqluser.add({set:{name:userName,password:randomPassword}});
176    var createdDatabase = mysqldb.add({set:{name:dbName,owner:userName}});
177    print("created user " + createdUser[0].name + " and database " + createdDatabase[0].name + " with password " + randomPassword);
178
179 ```
180
181 Die Funktion `createMySQLUserAndDB(args)` erzeugt den Datenbank-Nutzer und die Datenbank.
182 Da sich Datenbank und Datenbank-Nutzer nicht in die Quere kommen, haben sie der Einfachheit halber den gleichen Namen.
183
184 Beim Aufruf des Skripts muss eine Zeichenkette übergeben werden, die Bestandteil der Namen von Datenbank und Datenbank-Nutzer wird.
261280 185
JUH 186 ``` console
187 xyz00@h50:~$ ./createuseranddb.js my_domain_wordpress
188 created user and database xyz00_my_domain_wordpress with password 4fo=s3xY
189 ```
190
191 ::: attention
192 Merken Sie sich die Passworte, da Sie diese später benötigen. Bei einer
193 Datenbank-Anwendungen müssen Sie bei der Konfiguration den
194 Datenbank-Benutzer und sein Passwort angeben.
195 :::
196
197 ## Nutzung der Python-API {#kap-python-api}
198
2c93a1 199 Sie können HSAdmin auch remote über die Python-API des Programms ansprechen.
JUH 200 Das ermöglicht es Ihnen von einem entfernten Rechner aus HSAdmin zu bedienen.
201 Um mit der Python-API zu arbeiten müssen Sie zunächst die Python-Bindings für HSAdmin installieren.
261280 202
JUH 203 ### Installation von hs.admin.api
204
2c93a1 205 Wir installieren die Python-Bindings in einer virtuellen Python-Umgebung, sodass wir diese zunächst einrichten und aktivieren.
261280 206
JUH 207 ``` console
208 $ python3 -m venv /hsadmin
209 $ . /hsadmin/bin/activate
210 ```
2c93a1 211
JUH 212 <!-- todo: pipenv? -->
261280 213
JUH 214 Anschließend klonen wir die Python-Bindings und installieren sie.
215
216 ``` console
217 $ git clone https://dev.hostsharing.net//r/ansible/hs.admin.api.git
218 $ cd hs.admin.api
219 $ python setup.py install 
220 ```
221
2c93a1 222 Nun steht uns das Modul mit dem Python-Bindings in der virtuellen Umgebung zur Verfügung, sodass wir es in einem Skript importieren können.
261280 223
JUH 224 ### Python-Skript
225
2c93a1 226 Um die API in einem Skript nutzen zu können, müssen wir mit folgendem Code ein API-Objekt erzeugen.
261280 227
2c93a1 228 ```python
JUH 229 from hs.admin.api import API
261280 230
2c93a1 231 api = API(cas=dict(
JUH 232     uri='https://login.hostsharing.net/cas/v1/tickets',
233     service='https://config.hostsharing.net:443/hsar/backend'),
234     credentials=dict(username='xyz00', password='sehr-geheim'),
235     backends=[
236         'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin',
237         'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin'])
261280 238
2c93a1 239 api.user.add(set={'name': 'xyz00-domain.de', 'password': 'geheim', 'shell': '/bin/bash'})
JUH 240 api.domain.add(set={'name': 'domain.de', 'user': 'xyz00-domain.de'})
241 ```
261280 242
2c93a1 243 Nun ist es möglich, mit der üblichen Syntax HSAdmin im Skript anzusprechen.
JUH 244
245 Mit diesen beiden Befehlen legen wir beispielsweise einen Domain-Admin und eine neue Domain an.
246
247 ```python
248 api.user.add(set={'name': 'xyz00-domain.de', 'password': 'geheim', 'shell': '/bin/bash'})
249 api.domain.add(set={'name': 'domain.de', 'user': 'xyz00-domain.de'})
250 ```
261280 251
JUH 252 Eine Datenbank lässt sich folgendermaßen anlegen.
253
2c93a1 254 ```python
JUH 255 from hs.admin.api import API
261280 256
2c93a1 257 api = API(cas=dict(
JUH 258     uri='https://login.hostsharing.net/cas/v1/tickets',
259     service='https://config.hostsharing.net:443/hsar/backend'),
260     credentials=dict(username='xyz00', password='sehr-geheim'),
261     backends=[
262         'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin',
263         'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin'])
264
265 api.mysqluser.add(set={'name': 'xyz00_domain_de', 'password': 'geheim'})
266 api.mysqldb.add(set={'name': 'xyz00_domain_de', 'owner': 'xyz00_domain_de'})
267 ```
268
269 Nun wollen wir diese Befehle in ein Skript einbauen, das noch einige andere nützliche Dinge für uns erledigt.
270 Reseller und Webmaster, die viele Anwendungen betreuen, buchen häufig mehrere Pakete bei Hostsharing, sodass sie gerne ein Skript hätten, dem sie auch das Kürzel für das Paket übergeben können, in dem sie eine Domain mit Datenbank einrichten möchten.
271 Außerdem wäre es hilfreich, wenn das Skript dafür sorgt, dass Benutzernamen und Datenbankenname immer nach einem einheitlichen Schema erzeugt werden, sodass die Orientierung leichter fällt.
272 In unserem Beispielskript übergeben wir daher dem Skript drei Argumente:
261280 273
JUH 274 1.  das Kürzel für das Paket
275 2.  den Domainnamen
276 3.  eine Projekt-ID
277
2c93a1 278 Die Projekt-ID darf nicht mehr als 10 Zeichen umfassen, da sie zusammen mit dem fünfstelligen Paketkürzel in den Namen für Datenbank und Datenbank-Nutzer verwendet wird.
JUH 279 Diese dürfen aber nicht länger als 16 Zeichen sein.
280 Als Schema für eine Projekt-ID kommt also beispielsweise eine Kombination aus einer Kundennummer und einer Abkürzung in Frage.
281 Wir verwenden in unserem Beispiel dafür eine dreistellige Kundennummer und die Abkürzung `wp` für Wordpress.
282 Die Elemente trennen wir mit dem Unterstrich, da nur dieser als Namensbestandteil erlaubt ist.
261280 283
2c93a1 284 Wenn wir für den Kunden mit der Kundennummer 23 im Paket `xyz00` eine Domain für einen Wordpress-Blog einrichten möchten, lautet der Aufruf des Skripts folgendermaßen:
261280 285
JUH 286 ``` console
287 $ python createall.py xyz00 hs-example.de 023_wp
288 ```
289
290 Der Code des Skripts sieht so aus:
291
2c93a1 292 ```python
JUH 293 import random
294 import string
295 import sys
296 from hs.admin.api import API
297 from subprocess import check_output
261280 298
2c93a1 299 paketadmin = sys.argv[1]
JUH 300 domainname = sys.argv[2]
301 projektid = sys.argv[3]
261280 302
2c93a1 303 pw = check_output(["pass", "hostsharing/"+paketadmin]).decode("utf-8").strip("\n")
261280 304
2c93a1 305 api = API(cas=dict(
JUH 306     uri='https://login.hostsharing.net/cas/v1/tickets',
307     service='https://config.hostsharing.net:443/hsar/backend'),
308     credentials=dict(username=paketadmin, password=pw),
309     backends=[
310         'https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin',
311         'https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin'])
261280 312
2c93a1 313 def pwGen(stringLength=12):
JUH 314     """Function to generate a random password """
261280 315
2c93a1 316     password_characters = string.ascii_letters + string.digits
JUH 317     return ''.join(random.choice(password_characters) for i in range(stringLength))
318
319 pw_dadmin = pwGen()
320 pw_dbuser = pwGen()
321 dadmin = paketadmin+'-'+domainname.replace("-", "_")
322 dbuser = paketadmin+'_'+projektid
323 dbname = paketadmin+'_'+projektid
324
325 api.user.add(set={'name': dadmin, 'password': pw_dadmin, 'shell': '/bin/bash'})
326 api.domain.add(set={'name': domainname, 'user': dadmin})
327 api.mysqluser.add(set={'name': dbuser, 'password': pw_dbuser})
328 api.mysqldb.add(set={'name': dbname, 'owner': dbuser})
329
330 print("Domainname:" +domainname)
331 print("Domain-Admin: " + dadmin + " mit dem Passwort:" +pw_dadmin)
332 print("Datenbank-Nutzer: " +dbuser + " Passwort:" +pw_dbuser)
333 print("Datenbankname: " +dbname)
334 ```
335
336 In den ersten fünf Zeilen importieren wir einige Module bzw.
337 Funktionen, die wir benötigen.
338 In den Zeilen 7 bis 9 lesen wir die übergebenen Argumente aus und speichern die Werte in entsprechenden Variablen.
339
340 Um das API-Objekt zu erzeugen, benötigen wir das Passwort für den übergebenen Paket-Admin.
341 Wir lesen in Zeile 11 das Passwort aus dem verschlüsselten Passwort-Tresor des Kommandozeilenprogramms `pass` aus und speichern es in der Variablen `pw`.
342 Weitere Informationen zu dem Programm finden Sie auf der Website <https://www.passwordstore.org/>.
343 Sie können natürlich andere Programme wählen, um ein Passwort aus einem Passwort-Tresor auszulesen.
344 Falls Sie nur ein Paket bei Hostsharing verwalten, können Sie das Passwort auch direkt ins Skript eintragen.
345 Aus Sicherheitsgründen sollten Sie dies möglichst vermeiden.
346
347 Anschließend erzeugt das Skript das API-Objekt, wobei es als Credentials den Namen des Paket-Admin und sein Passwort übergibt.
348 Der Namen des Paket-Admin ist identisch mit dem Paket, in dem die Domain angelegt werden soll.
349
350 Danach wird ein Zufallsgenerator definiert, mit die Passworte erzeugt werden, die später benötigt werden.
351 In Zeile 27 und 28 werden die Passworte für den Domain-Admin und den Datenbank-Nutzer erzeugt und in Variablen gespeichert.
352 Direkt anschließend erzeugt das Skript aus den beim Aufruf übergebenen Werten die Namen für den Domain-Admin, den Datenbank-Nutzer und die Datenbank.
353
354 In den Zeilen 33 bis 36 werden der Domain-Admin, die Domain, den Datenbank-Nutzer und die Datenbank angelegt.
261280 355
JUH 356 Und zum Schluss gibt das Skript alle Daten aus.
357
2c93a1 358 Idealerweise würde ein solches Skript die neuen Benutzernamen mit den jeweiligen Passworten in den Passwort-Tresor eintragen, sodass dies nicht mit der Hand erledigt werden muss.
JUH 359
360 <!-- todo: Im Text werden Zeilennummern erwähnt. Wir brauchen eine Lösung dafür -->