aboutsummaryrefslogtreecommitdiffstats
path: root/backup-upload.rsc
blob: ef5b7c7284da2cea7695741e557e8e23c5817f45 (plain) (blame)
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
#!rsc by RouterOS
# RouterOS script: backup-upload
# Copyright (c) 2013-2024 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# provides: backup-script, order=50
# requires RouterOS, version=7.12
#
# create and upload backup and config file
# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-upload.md

:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }

:do {
  :local ScriptName [ :jobname ];

  :global BackupPassword;
  :global BackupRandomDelay;
  :global BackupSendBinary;
  :global BackupSendExport;
  :global BackupSendGlobalConfig;
  :global BackupUploadPass;
  :global BackupUploadUrl;
  :global BackupUploadUser;
  :global Domain;
  :global Identity;
  :global PackagesUpdateBackupFailure;

  :global CleanName;
  :global DeviceInfo;
  :global IfThenElse;
  :global LogPrint;
  :global MkDir;
  :global RandomDelay;
  :global ScriptFromTerminal;
  :global ScriptLock;
  :global SendNotification2;
  :global SymbolForNotification;
  :global WaitForFile;
  :global WaitFullyConnected;

  :if ($BackupSendBinary != true && \
       $BackupSendExport != true) do={
    $LogPrint error $ScriptName ("Configured to send neither backup nor config export.");
    :error false;
  }

  :if ([ $ScriptLock $ScriptName ] = false) do={
    :set PackagesUpdateBackupFailure true;
    :error false;
  }
  $WaitFullyConnected;

  :if ([ $ScriptFromTerminal $ScriptName ] = false && $BackupRandomDelay > 0) do={
    $RandomDelay $BackupRandomDelay;
  }

  # filename based on identity
  :local DirName ("tmpfs/" . $ScriptName);
  :local FileName [ $CleanName ($Identity . "." . $Domain) ];
  :local FilePath ($DirName . "/" . $FileName);
  :local BackupFile "none";
  :local ExportFile "none";
  :local ConfigFile "none";
  :local Failed 0;

  :if ([ $MkDir $DirName ] = false) do={
    $LogPrint error $ScriptName ("Failed creating directory!");
    :error false;
  }

  # binary backup
  :if ($BackupSendBinary = true) do={
    /system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
    $WaitForFile ($FilePath . ".backup");

    :do {
      /tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".backup") \
          user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".backup");
      :set BackupFile [ /file/get ($FilePath . ".backup") ];
      :set ($BackupFile->"name") ($FileName . ".backup");
    } on-error={
      $LogPrint error $ScriptName ("Uploading backup file failed!");
      :set BackupFile "failed";
      :set Failed 1;
    }

    /file/remove ($FilePath . ".backup");
  }

  # create configuration export
  :if ($BackupSendExport = true) do={
    /export terse show-sensitive file=$FilePath;
    $WaitForFile ($FilePath . ".rsc");

    :do {
      /tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".rsc") \
          user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".rsc");
      :set ExportFile [ /file/get ($FilePath . ".rsc") ];
      :set ($ExportFile->"name") ($FileName . ".rsc");
    } on-error={
      $LogPrint error $ScriptName ("Uploading configuration export failed!");
      :set ExportFile "failed";
      :set Failed 1;
    }

    /file/remove ($FilePath . ".rsc");
  }

  # global-config-overlay
  :if ($BackupSendGlobalConfig = true) do={
    # Do *NOT* use '/file/add ...' here, as it is limited to 4095 bytes!
    :execute script={ :put [ /system/script/get global-config-overlay source ]; } \
        file=($FilePath . ".conf\00");
    $WaitForFile ($FilePath . ".conf");

    :do {
      /tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".conf") \
          user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".conf");
      :set ConfigFile [ /file/get ($FilePath . ".conf") ];
      :set ($ConfigFile->"name") ($FileName . ".conf");
    } on-error={
      $LogPrint error $ScriptName ("Uploading global-config-overlay failed!");
      :set ConfigFile "failed";
      :set Failed 1;
    }

    /file/remove ($FilePath . ".conf");
  }

  :local FileInfo do={
    :local Name $1;
    :local File $2;

    :global FormatLine;
    :global HumanReadableNum;
    :global IfThenElse;

    :return \
      [ $IfThenElse ([ :typeof $File ] = "array") \
        ($Name . ":\n" . [ $FormatLine "    name" ($File->"name") ] . "\n" . \
          [ $FormatLine "    size" ([ $HumanReadableNum ($File->"size") 1024 ] . "iB") ]) \
        [ $FormatLine $Name $File ] ];
  }

  $SendNotification2 ({ origin=$ScriptName; \
    subject=[ $IfThenElse ($Failed > 0) \
      ([ $SymbolForNotification "floppy-disk,warning-sign" ] . "Backup & Config upload with failure") \
      ([ $SymbolForNotification "floppy-disk,arrow-up" ] . "Backup & Config upload") ]; \
    message=("Backup and config export upload for " . $Identity . ".\n\n" . \
      [ $DeviceInfo ] . "\n\n" . \
      [ $FileInfo "Backup file" $BackupFile ] . "\n" . \
      [ $FileInfo "Export file" $ExportFile ] . "\n" . \
      [ $FileInfo "Config file" $ConfigFile ]); silent=true });

  :if ($Failed = 1) do={
    :set PackagesUpdateBackupFailure true;
    :error false;
  }
} on-error={ }