sympl 15.7 KB
Newer Older
1
2
3
4
#!/bin/bash
#
# Sympl command line interface.
#
Paul Cammish's avatar
Paul Cammish committed
5
# Copyright 2019, Paul Cammish <sympl@kelduum.net>, part of the Sympl Project.
6
7
#
# Licenced under GPL3+
Paul Cammish's avatar
Paul Cammish committed
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
#
set -e

I_AM="$(whoami)"
VERBOSE=TRUE
FUNCTION=base
ACTION=none
TARGET=all

##############################################################################
#                              Output Functions                              #
##############################################################################

_debug() {
  if [ $DEBUG ]; then
    echo -e "\033[2mDEBUG: $@\033[0m"
  fi
}

_warn() {
  echo -e "\033[1m\033[33m WARN: \033[0m $@"
}

_error() {
  echo -e "\033[1m\033[31mERROR: \033[0m $@"
  exit 1
}

_verbose() {
  if [ $DEBUG ]; then
    echo " INFO: $@"
  elif [ $VERBOSE ]; then
    echo "$@"
  fi
}

##############################################################################
#                                    Help                                    #
##############################################################################

_help() {
  echo 'This is a big set of parser stuff.'
  exit 0
}

##############################################################################
#                              Support Functions                            #
##############################################################################

_func() {
  if [ $FUNCTION == base ]; then
    FUNCTION=$1
  else
    _error "Function '$FUNCTION' already selected, can't set to $1"
  fi
}

_action() {
  if [ $ACTION == none ]; then
    ACTION=$1
    if [ "$ACTION" == "set" ] && [ "x$3" != "x" ]; then
      OPTION=$2
      SETTING=$3
    fi
  else
    _error "Action '$ACTION' already selected, can't set to '$1'"
  fi
}

_is_domain() {

  if [ "$1" == "all" ]; then _error "Please specify a domain."; fi

  _debug "Checking if '$1' is a valid domain..."
  if [[ $1 =~ ^[0-9a-z\.-]+$ ]] && [[ $1 == *"."* ]] && [[ $1 != "."* ]] && [[ $1 != *"." ]]; then
    _debug "  $1 is valid"
  else
    _error "'$1' is not a valid domain"
  fi
}

_is_email() {
  _debug "Checking if '$1' is a valid email address..."


}

_is_database() {

  if [ "$1" == "all" ]; then _error "Please specify a database."; fi

  _debug "Checking if '$1' is a valid database... "

  if [[ $1 =~ ^[0-9A-Za-z_]+$ ]] ; then #&& [[ $(expr length $1) -le 32 ]]; then
    _debug "  $1 is valid"
  else
    _error "'$1' is not a valid database name"
  fi
}

##############################################################################
#                                      Base                                  #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
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
_base_none() {
  echo "Sympl command-line - a basic parser for common system administraton tasks.

Usage: sympl [function] [action] [target]

Where function is one of:
  web, mail, mysql, dns, ftp, cron, backup or blank for the system itself.
And action is one of:
  create, enable, disable, audit, update, destroy, set <item|option> <value>
And target is the domain/email address/database/etc.

Useful things:
 - Other than using set, the function, action and target can be in any order.
 - 'set' requires two arguments immediately after it, the option and value.
 - If more permissions are needed, you'll be prompted for your password.
 - 'destory' will only destroy something which has already been disabled.

Examples:

  sympl web create example.com

  sympl mysql disable example_db

  sympl enable mail username@example.com

  sympl audit backup

  sympl destroy cron example.com

  sympl example.com set only-ssl on

  sympl update

Note: Not all functions are implimented yet.
      Please report bugs via http://bugs.sympl.host.
"

}

Paul Cammish's avatar
Paul Cammish committed
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
_base_create() {
  _noop
}

_base_enable() {
  _noop
}

_base_disable() {
  _noop
}

_base_destroy() {
  _noop
}

_base_set() {
  _noop
}

_base_audit() {
  _noop
}

_base_update() {
Paul Cammish's avatar
Paul Cammish committed
176
177
178
179
  _debug "Updating Apt"
  sudo apt-get -qq update
  _debug "Upgrading installed packages"
  sudo apt-get -q -y install --only-upgrade 'sympl-*'
Paul Cammish's avatar
Paul Cammish committed
180
181
182
183
184
185
}

##############################################################################
#                                       Web                                  #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
186
187
188
189
_web_none() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
_web_create() {

  _is_domain $1

  _debug "Check for disabled sites"
  if [ -d /srv/__disabled__$1/public/htdocs ]; then
    _error "The domain $1 is disabled. Use 'sympl enable $1' to enable it."
  elif [ -d /srv/$1/public/__disabled__htdocs ] ; then
    _error "The website $1 is disabled. Use 'sympl web enable $1' to enable it."
  fi

  _debug "Check to see if $1 already exists"
  if [ -d /srv/$1/public/htdocs ]; then
    _error "$1 Already exists."
  fi

  _verbose "Creating Website for $1 at /srv/$1/public/htdocs..."
  mkdir -p "/srv/$1/public/htdocs"
208
209
  chmod -R 2775 "/srv/$1/public" > /dev/null 2>&1
  chown -R www-data:www-data "/srv/$1/public" > /dev/null 2>&1
Paul Cammish's avatar
Paul Cammish committed
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

}

_web_enable() {

  _is_domain $1

  _debug "Checking $1 is disabled and exists"
  if [ -d /srv/$1/public/htdocs ] || [ ! -d /srv/$1/public/__disabled__htdocs ]; then
    _error "The website $1 is already enabled."
  elif [ ! -d /srv/$1 ]; then
    _error "The domain $1 does not exist."
  fi

  _verbose "Enabling Website $1"
  mv /srv/$1/public/__disabled__htdocs /srv/$1/public/htdocs

}

_web_disable() {

  _is_domain $1

  _debug "Checking $1 is enabled and exists"
  if [ -d /srv/$1/public/__disabled__htdocs ]; then
    _error "The website $1 is already disabled."
  elif [ ! -d /srv/$1/public/htdocs ]; then
    _error "The website $1 does not exist."i
  fi

  _verbose "Disabling Website $1"
  mv /srv/$1/public/htdocs /srv/$1/public/__disabled__htdocs

}

_web_destroy() {

  _is_domain $1

  _debug "Confirm '$1' is disabled and exists"
  if [ -d /srv/$1/public/htdocs ]; then
    _error "The website '$1' is enabled. It must be disabled before it can be destroyed."
  elif [ ! -d /srv/$1/public/__disabled__htdocs ]; then
    _error "The website '$1' does not exist."
  elif [ ! -d /srv/$1 ]; then
    _error "The domain '$1' does not exist."
  fi

  _verbose "Destroying /srv/$1/public/__disabled__htdocs..."
  rm -r /srv/$1/public/__disabled__htdocs/
}

_web_audit() {

  # TODO: List details of specific site, otherwise list all sites and any aliasses.

  if [ "$1" != "all" ]; then _is_domain $1 ; fi

  find /srv/*/public/ -type d -name '*htdocs' > /dev/shm/sympl_web_audit

  _verbose "Enabled sites:"
  grep -v __disabled__ /dev/shm/sympl_web_audit | cut -d '/' -f 3 | sort

  _verbose "Disabled sites:"
  grep __disabled__ /dev/shm/sympl_web_audit | cut -d '/' -f 3 | sort

}

_web_set() {
  _noop
Paul Cammish's avatar
Paul Cammish committed
280
}
Paul Cammish's avatar
Paul Cammish committed
281

Paul Cammish's avatar
Paul Cammish committed
282
283
_web_update() {
  _noop
Paul Cammish's avatar
Paul Cammish committed
284
285
286
287
288
289
}

##############################################################################
#                                Mysql/MariaDB                               #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
290
291
292
_mysql_none() {
  _noop
}
Paul Cammish's avatar
Paul Cammish committed
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

_mysql_create() {

  _is_database $1

  _debug "Check if $1 already exists"
  if [ $( mysql -NBe 'show databases;' | grep -c "^$1$" ) -eq 0 ]; then
    if [ $( mysql -NBe "use mysql; select User from user;" | grep -c "^$1$" ) -eq 0 ]; then
      _verbose "Creating database '$1'..."
      password="$( openssl rand -base64 32 | cut -c 1-32 )"
      _debug "Password '$password', creating DB -- CREATE DATABASE $1;"
      mysql -e "CREATE DATABASE $1;"
      _debug 'Creating user -- GRANT ALL PRIVILEGES ON $1.* TO '$1'@'localhost' IDENTIFIED BY '$password';'
      mysql -e "GRANT ALL PRIVILEGES ON $1.* TO '$1'@'localhost' IDENTIFIED BY '$password';"
      _debug 'Outputting password'
      echo "$password" >> /home/sympl/mysql_$1_password
      _debug 'Securing file'
      chmod 600 /home/sympl/mysql_$1_password
      chown sympl:sympl /home/sympl/mysql_$1_password
      _verbose "Database '$1' created with user '$1' and password '$password'"
      _verbose "  saved to /home/sympl/mysql_$1_password"
    else
      _error "User '$1' already exists."
    fi
  else
    _error "Database '$1' already exists."
  fi
}

_mysql_enable() {

  _is_database $1

  _debug "Check if $1 exists and is disabled"
  if [ $( mysql -NBe 'show databases;' | grep -c "^$1$" ) -eq 1 ]; then
    if [ $( mysql -NBe "use mysql; select User from user;" | grep -c "^$1$" ) -eq 1 ]; then
      if [ $( mysql -NBe "SHOW GRANTS for '$1'@'localhost'" 2> /dev/null | grep -c "^GRANT ALL PRIVILEGES ON \`$1\`.* TO '$1'@'localhost'$" ) -eq 0 ]; then
        _verbose "Enabling user '$1' for database '$1'"
        mysql -e "GRANT ALL PRIVILEGES ON $1.* TO '$1'@'localhost'"
      else
        _error "User '$1' is already enabled for database '$1'."
      fi
    else
      _error "User '$1'@'localhost' does not exist, although the database does."
    fi
  else
    _error "Database '$1' does not exist."
  fi

}

_mysql_disable() {

  _is_database $1

  _debug "Check if $1 exists and is enabled"
  if [ $( mysql -NBe 'show databases;' | grep -c "^$1$" ) -eq 1 ]; then
    if [ $( mysql -NBe "use mysql; select User from user;" | grep -c "^$1$" ) -eq 1 ]; then
      if [ $( mysql -NBe "SHOW GRANTS for '$1'@'localhost'" 2> /dev/null | grep -c "^GRANT ALL PRIVILEGES ON \`$1\`.* TO '$1'@'localhost'$" ) -eq 1 ]; then
        _verbose "Disabling user '$1' for database '$1'"
        mysql -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$1'@'localhost';"
      else
        _error "Database '$1' is already disabled for database '$1'."
      fi
    else
      _error "User '$1'@'localhost' does not exist, although the database does."
    fi
  else
    _error "Database '$1' does not exist."
  fi

}

_mysql_destroy() {

  _is_database $1

  _debug "Check if $1 exists and is disabled"
  if [ $( mysql -NBe 'show databases;' | grep -c "^$1$" ) -eq 1 ]; then
    if [ $( mysql -NBe "use mysql; select User from user;" | grep -c "^$1$" ) -eq 1 ]; then
      if [ $( mysql -NBe "SHOW GRANTS for '$1'@'localhost'" 2> /dev/null | grep -c "^GRANT ALL PRIVILEGES ON \`$1\`.* TO '$1'@'localhost'$" ) -eq 0 ]; then
        _verbose "Destroying database and user '$1'"
        mysql -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$1'@'localhost';"
        mysql -e "DROP USER '$1'@'localhost';"
        mysql -e "DROP DATABASE $1;"
      else
        _error "Database '$1' is not disabled. Please disable it with 'sympl mysql disable $1'"
      fi
    else
      _error "User '$1' does not exist, but the database does."
    fi
  else
    _error "Database '$1' does not exist."
  fi
}

_mysql_audit() {
  mysql -e 'show databases;'
  mysql -e 'use mysql; select User from user;'
}

Paul Cammish's avatar
Paul Cammish committed
394
395
396
397
_mysql_update() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
398
##############################################################################
Paul Cammish's avatar
Paul Cammish committed
399
#                                     DNS                                    #
Paul Cammish's avatar
Paul Cammish committed
400
401
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
402
_dns_none() {
Paul Cammish's avatar
Paul Cammish committed
403
404
405
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
406
_dns_create() {
Paul Cammish's avatar
Paul Cammish committed
407
408
409
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
410
_dns_enable() {
Paul Cammish's avatar
Paul Cammish committed
411
412
413
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
414
_dns_disable() {
Paul Cammish's avatar
Paul Cammish committed
415
416
417
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
418
_dns_destroy() {
Paul Cammish's avatar
Paul Cammish committed
419
420
421
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
422
423
424
425
426
427
428
429
430
_dns_set() {
  _noop
}

_dns_audit() {
  _noop
}

_dns_update() {
Paul Cammish's avatar
Paul Cammish committed
431
432
433
434
435
436
437
  _noop
}

##############################################################################
#                                     Mail                                   #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
438
439
440
441
_mail_none() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
_mail_create() {
  _noop
}

_mail_enable() {
  _noop
}

_mail_disable() {
  _noop
}

_mail_destroy() {
  _noop
}

_mail_set() {
  _noop
}

_mail_audit() {
  _noop
}

##############################################################################
#                                     FTP                                    #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
470
471
472
473
_ftp_none() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
_ftp_create() {
  _noop
}

_ftp_enable() {
  _noop
}

_ftp_disable() {
  _noop
}

_ftp_destroy() {
  _noop
}

_ftp_set() {
  _noop
}

_ftp_audit() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
498
499
500
501
_ftp_update() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
502
503
504
505
##############################################################################
#                                    Backup                                  #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
506
507
508
509
_backup_none() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
_backup_create() {
  _verbose "Taking backup..."
  sudo backup2l -b
}

_backup_enable() {
  if [ ! -x /etc/cron.daily/zz-backup2l ]; then
    _verbose "Enabling backups."
    sudo chmod +x /etc/cron.daily/zz-backup2l
  else
    _error "Backups are already enabled."
  fi
}

_backup_disable() {
  _verbose "Disabling backups."
  if [ -x /etc/cron.daily/zz-backup2l ]; then
    _verbose "Disabling backups."
    sudo chmod -x /etc/cron.daily/zz-backup2l
  else
    _error "Backups are already disabled."
  fi
}

_backup_destroy() {
  if [ $( backup2l -s | grep -c '^all.2 ' ) -ge 1 ]; then
    _verbose "Removing oldest backup set."
    sudo backup2l -p 1 > /dev/null
  else
    _error "Not removing only backup set."
  fi
}

_backup_set() {
  _error "Backup has no settings."
}

_backup_audit() {
  _verbose "Backup status:"
  backup2l -s
}

Paul Cammish's avatar
Paul Cammish committed
552
553
554
555
_backup_audit() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
556
557
558
559
##############################################################################
#                                     Cron                                   #
##############################################################################

Paul Cammish's avatar
Paul Cammish committed
560
561
562
563
_cron_none() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
_cron_create() {
  _noop
}

_cron_enable() {
  _noop
}

_cron_disable() {
  _noop
}

_cron_destroy() {
  _noop
}

_cron_set() {
  _noop
}

_cron_audit() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
588
589
590
591
_cron_update() {
  _noop
}

Paul Cammish's avatar
Paul Cammish committed
592
593
594
595
596
597
##############################################################################
#                                  NoOp Stub                                 #
##############################################################################


_noop() {
Paul Cammish's avatar
Paul Cammish committed
598
  _warn "Sorry this doesn't do anything yet, but it may be in a new version.\n        Run 'sympl update' for an updated version."
Paul Cammish's avatar
Paul Cammish committed
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  exit 0
}

##############################################################################
#                              Handle Command Line                           #
##############################################################################

_main() {

  UNHANDLED=()
  while [ $# -gt 0 ]; do
    case $1 in
      --debug)                  DEBUG=TRUE               ; shift ;;
      --quiet|-q)               VERBOSE=FALSE            ; shift ;;
      web|http|website)         _func web                ; shift ;;
      mail|email)               _func mail               ; shift ;;
      mysql|database|mariadb)   _func mysql              ; shift ;;
      dns|domain)               _func dns                ; shift ;;
      backup)                   _func backup             ; shift ;;
      cron)                     _func cron               ; shift ;;
      ftp)                      _func ftp                ; shift ;;
      create)                   _action 'create'         ; shift ;;
      destroy)                  _action 'destroy'        ; shift ;;
      enable)                   _action 'enable'         ; shift ;;
      disable)                  _action 'disable'        ; shift ;;
      audit|list)               _action 'audit'          ; shift ;;
Paul Cammish's avatar
Paul Cammish committed
625
      update|upgrade)           _action 'update'         ; shift ;;
Paul Cammish's avatar
Paul Cammish committed
626
627
628
629
630
631
632
633
634
635
636
637
      set)                      _action 'set' "$2" "$3"  ; shift ; shift ; shift ;;
      *) # unhandled parameter
        if [ $TARGET = all ]; then
          TARGET="$1"
        else
          UNHANDLED+=("$1")
        fi
        shift # past argument
      ;;
    esac
  done

Paul Cammish's avatar
Paul Cammish committed
638
639
640
641
  _debug "Command line parameters: $@"

  _debug "Running as '$I_AM', EUID '$EUID'"

Paul Cammish's avatar
Paul Cammish committed
642
643
644
645
646
647
648
649
650
  _debug "Runtime variables:
  Unhanded         | $UNHANDLED
  FUNCTION         | $FUNCTION
  ACTION           | $ACTION
  TARGET           | $TARGET
  OPTION           | $OPTION
  SETTING          | $SETTING"

  if [ "x$UNHANDLED" != "x" ]; then
Paul Cammish's avatar
Paul Cammish committed
651
    _error "Unexpected input: '$UNHANDLED', run 'sympl' for help."
Paul Cammish's avatar
Paul Cammish committed
652
653
654
655
656
657
658
659
  fi

  _${FUNCTION}_${ACTION} $TARGET $OPTION $SETTING

}


_main $@
660

Paul Cammish's avatar
Paul Cammish committed
661
exit 0