mirror of
https://github.com/eworm-de/routeros-scripts
synced 2024-05-14 08:04:19 +00:00
5101d57d52
Currently backup to MikroTik cloud is pretty unreliable and script can not catch errors at runtime. Looks like this does not change any time soon (Ticket#2019052022003204). So let's just split off the cloud backup to make sure email backup works as expected.
223 lines
6.2 KiB
Text
223 lines
6.2 KiB
Text
#!rsc
|
|
# RouterOS script: global-functions
|
|
# Copyright (c) 2013-2019 Christian Hesse <mail@eworm.de>
|
|
#
|
|
# global functions
|
|
|
|
# expected configuration version
|
|
:global ExpectedConfigVersion 5;
|
|
|
|
# global variables not to be changed by user
|
|
:global SentConfigChangesNotification "-";
|
|
:global SentRouterosUpdateNotification "-";
|
|
:global SentLteFirmwareUpgradeNotification "-";
|
|
:global Identity [ / system identity get name ];
|
|
|
|
# url encoding
|
|
:global UrlEncode do={
|
|
:local Input [ :tostr $1 ];
|
|
:local Return "";
|
|
|
|
:if ([ :len $Input ] > 0) do={
|
|
:local Chars " !\"#\$%&'()*+,-./:;<=>\?@[\\]^_`{|}~";
|
|
:local Subs { "%20"; "%21"; "%22"; "%23"; "%24"; "%25"; "%26"; "%27"; "%28"; "%29";
|
|
"%2A"; "%2B"; "%2C"; "%2D"; "%2E"; "%2F"; "%3A"; "%3B"; "%3C"; "%3D";
|
|
"%3E"; "%3F"; "%40"; "%5B"; "%5C"; "%5D"; "%5E"; "%5F"; "%60"; "%7B";
|
|
"%7C"; "%7D"; "%7E" };
|
|
|
|
:for I from=0 to=([ :len $Input ] - 1) do={
|
|
:local Char [ :pick $Input $I ];
|
|
:local Replace [ :find $Chars $Char ];
|
|
|
|
:if ([ :len $Replace ] > 0) do={
|
|
:set Char ($Subs->$Replace);
|
|
}
|
|
:set Return ($Return . $Char);
|
|
}
|
|
}
|
|
|
|
:return $Return;
|
|
}
|
|
|
|
# character replace
|
|
:global CharacterReplace do={
|
|
:local String [ :tostr $1 ];
|
|
:local ReplaceFrom [ :tostr $2 ];
|
|
:local ReplaceWith [ :tostr $3 ];
|
|
:local Len [ :len $ReplaceFrom ];
|
|
:local Return "";
|
|
|
|
:if ($ReplaceFrom = "") do={
|
|
:return $String;
|
|
}
|
|
|
|
:while ($String ~ $ReplaceFrom) do={
|
|
:local Pos [ :find $String $ReplaceFrom ];
|
|
:set Return ($Return . [ :pick $String 0 $Pos ] . $ReplaceWith);
|
|
:set String [ :pick $String ($Pos + $Len) 999 ];
|
|
}
|
|
|
|
:return ($Return . $String);
|
|
}
|
|
|
|
# check and import required certificates
|
|
:global CertificateAvailable do={
|
|
:local CommonName [ :tostr $1 ];
|
|
|
|
:global ScriptUpdatesBaseUrl;
|
|
:global ScriptUpdatesUrlSuffix;
|
|
|
|
:global UrlEncode;
|
|
:global WaitForFile;
|
|
|
|
:if ([ / certificate print count-only where common-name=$CommonName ] = 0) do={
|
|
:log info ("Certificate with CommonName " . $CommonName . \
|
|
" not available, downloading and importing.");
|
|
:do {
|
|
:local LocalFileName ($CommonName . ".pem");
|
|
:local UrlFileName ([ $UrlEncode $CommonName ] . ".pem");
|
|
/ tool fetch check-certificate=yes-without-crl \
|
|
($ScriptUpdatesBaseUrl . "certs/" . \
|
|
$UrlFileName . $ScriptUpdatesUrlSuffix) \
|
|
dst-path=$LocalFileName;
|
|
$WaitForFile $LocalFileName;
|
|
/ certificate import file-name=$LocalFileName passphrase="";
|
|
/ file remove $LocalFileName;
|
|
} on-error={
|
|
:log warning "Failed imprting certificate!";
|
|
}
|
|
}
|
|
}
|
|
|
|
# send notification via e-mail and telegram
|
|
# Note that attachment is ignored for telegram!
|
|
:global SendNotification do={
|
|
:local Subject [ :tostr $1 ];
|
|
:local Message [ :tostr $2 ];
|
|
:local Attach [ :tostr $3 ];
|
|
|
|
:global Identity;
|
|
:global EmailGeneralTo;
|
|
:global EmailGeneralCc;
|
|
:global TelegramTokenId;
|
|
:global TelegramChatId;
|
|
|
|
:global UrlEncode;
|
|
:global CertificateAvailable;
|
|
|
|
:if ([ :len $EmailGeneralTo ] > 0) do={
|
|
:do {
|
|
/ tool e-mail send to=$EmailGeneralTo cc=$EmailGeneralCc \
|
|
subject=("[" . $Identity . "] " . $Subject) body=$Message file=$Attach;
|
|
} on-error={
|
|
:log warning "Failed sending notification mail!";
|
|
}
|
|
}
|
|
|
|
:if ([ :len $TelegramTokenId ] > 0 && [ :len $TelegramChatId ] > 0) do={
|
|
$CertificateAvailable "Go Daddy Secure Certificate Authority - G2";
|
|
:do {
|
|
/ tool fetch check-certificate=yes-without-crl keep-result=no http-method=post \
|
|
("https://api.telegram.org/bot" . $TelegramTokenId . "/sendMessage") \
|
|
http-data=("chat_id=" . $TelegramChatId . "&text=" . \
|
|
[ $UrlEncode ("[" . $Identity . "] " . $Subject . "\n\n" . $Message) ]);
|
|
} on-error={
|
|
:log warning "Failed sending telegram notification!";
|
|
}
|
|
}
|
|
}
|
|
|
|
# get MAC vendor
|
|
:global GetMacVendor do={
|
|
:local Mac [ :tostr $1 ];
|
|
|
|
:global CertificateAvailable;
|
|
|
|
:do {
|
|
:local Vendor;
|
|
$CertificateAvailable "Let's Encrypt Authority X3";
|
|
:set Vendor ([ / tool fetch check-certificate=yes-without-crl \
|
|
("https://api.macvendors.com/" . [ :pick $Mac 0 8 ]) output=user as-value ]->"data");
|
|
:return $Vendor;
|
|
} on-error={
|
|
:return "unknown vendor";
|
|
}
|
|
}
|
|
|
|
# clean file path
|
|
:global CleanFilePath do={
|
|
:local Path [ :tostr $1 ];
|
|
|
|
:global CharacterReplace;
|
|
|
|
:while ($Path ~ "//") do={
|
|
:set $Path [ $CharacterReplace $Path "//" "/" ];
|
|
}
|
|
:if ([ :pick $Path 0 ] = "/") do={
|
|
:set Path [ :pick $Path 1 [ :len $Path ] ];
|
|
}
|
|
:if ([ :pick $Path ([ :len $Path ] - 1) ] = "/") do={
|
|
:set Path [ :pick $Path 0 ([ :len $Path ] - 1) ];
|
|
}
|
|
|
|
:return $Path;
|
|
}
|
|
|
|
# download package from upgrade server
|
|
:global DownloadPackage do={
|
|
:local PkgName [ :tostr $1 ];
|
|
:local PkgVer [ :tostr $2 ];
|
|
:local PkgArch [ :tostr $3 ];
|
|
:local PkgDir [ :tostr $4 ];
|
|
|
|
:global CertificateAvailable;
|
|
:global CleanFilePath;
|
|
:global WaitForFile;
|
|
|
|
:if ([ :len $PkgName ] = 0) do={ return false; }
|
|
:if ([ :len $PkgVer ] = 0) do={ :set PkgVer [ / system package update get installed-version ]; }
|
|
:if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ / system resource get architecture-name ]; }
|
|
|
|
:local PkgFile ($PkgName . "-" . $PkgVer . "-" . $PkgArch . ".npk");
|
|
:local PkgDest [ $CleanFilePath ($PkgDir . "/" . $PkgFile) ];
|
|
|
|
$CertificateAvailable "Let's Encrypt Authority X3";
|
|
:do {
|
|
/ tool fetch check-certificate=yes-without-crl \
|
|
("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile) \
|
|
dst-path=$PkgDest;
|
|
$WaitForFile $PkgDest;
|
|
} on-error={
|
|
/ file remove [ find where name=$PkgDest ];
|
|
:return false;
|
|
}
|
|
|
|
:return true;
|
|
}
|
|
|
|
# lock script against multiple invocation
|
|
:global ScriptLock do={
|
|
:local Script [ :tostr $1 ];
|
|
|
|
:if ([ / system script job print count-only where script=$Script ] > 1) do={
|
|
:log debug ("Script " . $Script . " started more than once... Aborting.");
|
|
:error "Locked."
|
|
}
|
|
}
|
|
|
|
# wait for file to be available
|
|
:global WaitForFile do={
|
|
:global CleanFilePath;
|
|
|
|
:local FileName [ $CleanFilePath [ :tostr $1 ] ];
|
|
:local I 0;
|
|
|
|
:while ([ file print count-only where name=$FileName ] = 0) do={
|
|
:if ($I > 20) do={
|
|
:return false;
|
|
}
|
|
:delay 100ms;
|
|
:set I ($I + 1);
|
|
}
|
|
:return true;
|
|
}
|