Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
#!/bin/bash
# Command line for ISPConfig remote user REST API using either smart functions or raw methods.
# Author: Johan Ehnberg, johan@molnix.com
set -e
### Variables
VERSION=2018-04-23
PROGNAME=$(basename $0)
DATESTAMP=`date +%s`
### Common commands
# usage
usage() {
echo "Command line for ISPConfig remote user REST API using either smart functions or raw methods."
echo
echo "Usage: $PROGNAME -h/-f <function>/-m <method> [options] ..."
echo
echo "Common options:"
echo
echo " -a <file>"
echo " Config file. Options are read in the following order: system configuration, user configuration, the file specified in this option, other command line options. The last occurrence overrides previous ones."
echo
echo " -e <url>"
echo " API endpoint url such as https://myserver.example.com:8080/remote/json.php ."
echo
echo " -h"
echo " Show this help text."
echo
echo " -i <id>"
echo " Server id (defaults to 1)."
echo
echo " -k"
echo " Do not validate server certificate (for self-signed certificates)."
echo
echo " -q"
echo " Quiet, only outputs results."
echo
echo " -v"
echo " Verbose, outputs all info where available."
echo
echo "Functions combine several methods to carry out common tasks. Function options:"
echo
echo " -c <client>"
echo " Client user name to use."
echo
echo " -f <function>"
echo " Function to perform, such as dns_a_add. Cannot be used with -m, -d, -j or -s."
echo
echo " -p <password>"
echo " Password of the remote user specified in ISPConfig."
echo
echo " -u <user>"
echo " Name of the remote user specified in IPSConfig."
echo
echo " Available functions:"
echo
echo " clients List all clients"
echo " dns_a_add <zone> <name> <ip> Add or update a DNS A record"
echo " dns_a_delete <zone> <name> Delete a DNS A record"
echo " dns_rr <zone> List all records for a zone"
echo " dns_zones List all zones"
echo " log_in Create a session (not needed by default)"
echo " log_out <session> Log out a session (not needed by default)"
echo
echo "Using a method wraps the raw request on the command line. Method options:"
echo
echo " -d <string>"
echo " Read JSON data from command line. Use escapes and quotes! Cannot be used with -j or -s."
echo
echo " -j <file>"
echo " Read JSON data from file. Cannot be used with -d or -s."
echo
echo " -m <method>"
echo " Raw method to use such as dns_a_add. Cannot be used with -f. Requires one of -d, -j or -s."
echo
echo " -s"
echo " Read JSON data from stdin. Cannot be used with -d or -j."
echo
echo "For details on methods, see:"
echo "https://git.ispconfig.org/ispconfig/ispconfig3/tree/master/remoting_client/API-docs"
echo
echo "Config files are bash files that can contain the following variables (with examples):"
echo
echo "remote_user=myuser # see -u"
echo "remote_password=mypassword # see -p"
echo "remote_url=https://myserver.example.com:8080/remote/json.php # see -e"
echo "client_user=myclient # see -c"
echo "server_id=1 # see -i"
echo "ssl_validate=off # see -k"
echo
echo "Example uses:"
echo " 1. Update a DNS A record or update if it already exists"
echo " ispconfig-cli -f \"dns_a_add example.com. johnscomputer 192.168.0.99\""
echo
}
# message verbosity message
message() {
if [ $1 -le $VERBOSITY ]; then
MESSAGE="${MESSAGE}${2}"
fi
}
# fail dump
fail() {
echo -e "$MESSAGE"
echo "Something went wrong. Here is the last response:"
echo $1
log_out
exit 1
}
# restCall method data
restCall() {
curl $CURLK -sS -X POST -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d "${2}" "${remote_url}?${1}"
}
# method method
method() {
restCall $1 "$JSONDATA"
}
### Functions
# List all clients
# clients
clients() {
clientGet | jq .response
}
# Add or update an A record
# dns_a_add zone name ip
dns_a_add() {
dns_zone_id $1
dns_a_id $1 $2
if [[ $dns_a_id =~ ^-?[0-9]+$ ]]; then
message 2 "DNS A $2 exists with id $dns_a_id, updating rows: "
message 1 "`dnsUpdateAByIdAndIp $dns_a_id $3 | jq -r .response`"
elif [[ $dns_a_id == "" ]]; then
message 2 "DNS A $2 does not exist, created ID: "
message 1 "`dnsAddAByZoneAndNameAndIp $dns_zone_id $2 $3 | jq -r .response`\n"
else
fail $dns_a_id
fi
}
# Delete an A record if it exists
# dns_a_delete zone name
dns_a_delete() {
dns_zone_id $1
dns_a_id $1 $2
if [[ $dns_a_id =~ ^-?[0-9]+$ ]]; then
message 2 "DNS A $2 has id $dns_a_id, deleted rows: "
message 1 "`dnsDeleteAById $dns_a_id | jq -r '.response'`\n"
else
message 2 "DNS A $2 does not exist, skipping.\n"
fi
}
# List all records for a zone
# dns_rr zone
dns_rr() {
dns_zone_id $1
dnsGetRrByZone $dns_zone_id | jq .response
}
# List all zones
# dns_zones
dns_zones() {
dnsGetZones | jq .response
}
# Log in
log_in() {
session_id=`restCall login "{\"username\": \"${remote_user}\",\"password\": \"${remote_password}\"}" | jq -r '.response'`
if [[ $session_id == "false" ]]; then
fail "Login failed!"
else
message 3 "Logged in with session_id $session_id as $remote_user.\n"
client_id $client_user
fi
}
# Log out
# log_out session
log_out() {
if [[ `restCall logout "{\"session_id\": \"${1}\"}" |jq -r .response` == "true" ]]; then
message 3 "Logged out session $1 successfully.\n"
else
fail "Logging out failed!"
fi
}
### ID helpers
# Due to bash limitations, id's should only be set in _id functions below.
# Do not run subshells anywhere else.
# This is due to subshell nesting will otherwise lose the variables.
# Get client id
# client_id client_user
client_id() {
client_id=`clients | jq -r ".[] | select(.username == \"${1}\") | .client_id"`
message 3 "Client $1 has id $client_id.\n"
}
# Get dns A id
# dns_a_id zone name
dns_a_id() {
dns_a_id=`dns_rr $1 | jq -r ".[] | select(.name == \"${2}\") | .id"`
message 3 "DNS A $2 has id $dns_a_id.\n"
}
# Get zone id
# dns_zone_id zone
dns_zone_id() {
dns_zone_id=`dns_zones | jq -r ".[] | select(.origin == \"${1}\") | .id"`
message 3 "DNS zone $1 has id $dns_zone_id.\n"
}
### Methods
# Get clients
clientGet() {
restCall client_get "{\"session_id\": \"${session_id}\",\"client_id\":{}}"
}
# Add A by zone and name and IP
dnsAddAByZoneAndNameAndIp() {
restCall dns_a_add "{\"session_id\": \"${session_id}\",\"client_id\": \"${client_id}\",\"params\": {\"server_id\": ${SERVER},\"zone\": \"${1}\",\"name\": \"${2}\",\"type\": \"a\",\"data\": \"${3}\",\"aux\": \"0\", \"ttl\": \"3600\", \"active\": \"y\", \"stamp\": \"${datestamp}\", \"serial\": \"1\"}}"
}
# Delete A by id
dnsDeleteAById() {
restCall dns_a_delete "{\"session_id\": \"${session_id}\",\"primary_id\": \"${1}\"}"
}
# Get RR by id
dnsGetRrByZone() {
restCall dns_rr_get_all_by_zone "{\"session_id\": \"${session_id}\",\"zone_id\": \"${1}\"}"
}
# Get zones
dnsGetZones() {
restCall dns_zone_get_by_user "{\"session_id\": \"${session_id}\",\"client_id\": \"${client_id}\",\"server_id\": ${SERVER}}"
}
# Update A by id and IP
dnsUpdateAByIdAndIp() {
restCall dns_a_update "{\"session_id\": \"${session_id}\",\"client_id\": \"${client_id}\",\"primary_id\": \"${1}\",\"params\": {\"data\": \"${2}\", \"stamp\": \"${datestamp}\"}}"
}
### Run
# Check dependencies
if ! [ -x "$(command -v curl)" ]; then
echo 'Error: curl is not installed.' >&2
exit 1
fi
if ! [ -x "$(command -v jq)" ]; then
echo 'Error: jq is not installed.' >&2
exit 1
fi
# Check config files
if [ -r /etc/ispconfig-cli.conf ]; then
. /etc/ispconfig-cli.conf
fi
if [ -r ~/.ispconfig-cli ]; then
. ~/.ispconfig-cli
fi
# Check command line
if [[ $1 == "" ]]; then
usage
exit 1
fi
SERVER=1
VERBOSITY=2
while getopts :a:e:hi:kqvc:f:p:u:d:j:m:s opt; do
case $opt in
a)
if [[ -e $OPTARG ]]; then
source $OPTARG
else
echo "Config file $OPTARG not found!"
exit 1
fi
;;
e)
remote_url=$OPTARG
;;
h)
usage
exit 1
;;
i)
SERVER=$OPTARG
;;
k)
$ssl_validate=off
;;
q)
if [[ $VERBOSITY == "2" ]]; then
VERBOSITY=1
else
echo "-q and -v cannot be specified at the same time!"
exit 1
fi
;;
v)
if [[ $VERBOSITY == "2" ]]; then
VERBOSITY=3
else
echo "-q and -v cannot be specified at the same time!"
exit 1
fi
;;
c)
client_user=$OPTARG
;;
f)
if [[ $METHOD == "" ]]; then
FUNCTION=$OPTARG
else
echo "Function and method cannot be specified at the same time!"
exit 1
fi
;;
p)
remote_password=$OPTARG
;;
u)
remote_user=$OPTARG
;;
d)
if [[ $JSONMODE == "" ]]; then
JSONMODE=cli
JSONDATA=$OPTARG
else
echo "You can only use one JSON data source!"
exit 1
fi
;;
j)
if [[ $JSONMODE == "" ]]; then
JSONMODE=fil
JSONDATA=`cat $OPTARG`
else
echo "You can only use one JSON data source!"
exit 1
fi
;;
m)
if [[ $FUNCTION == "" ]]; then
METHOD=$OPTARG
else
echo "Function and method cannot be specified at the same time!"
exit 1
fi
;;
s)
if [[ $JSONMODE == "" ]]; then
JSONMODE=std
JSONDATA=`cat`
else
echo "You can only use one JSON data source!"
exit 1
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
if [[ $remote_url == "" ]]; then
echo "No url provided!"
exit 1
fi
if [[ $ssl_validate == "off" ]]; then
CURLK="-k"
fi
if [[ $METHOD != "" ]]; then
method $METHOD
elif [[ $FUNCTION == log_* ]]; then
$FUNCTION
elif [[ $FUNCTION != "" ]]; then
log_in
$FUNCTION
log_out $session_id
else
echo "Neither method nor functions specified!"
exit 1
fi
echo -e $MESSAGE
exit 0