routeros-scripts/global-functions
2019-02-14 20:35:13 +01:00

194 lines
5.4 KiB
Text

#!rsc
# RouterOS script: global-functions
# Copyright (c) 2013-2019 Christian Hesse <mail@eworm.de>
#
# global functions
# expected configuration version
:global ExpectedConfigVersion 2;
# global variables not to be changed by user
:global SentRouterosUpdateNotification "-";
:global SentLteFirmwareUpgradeNotification "-";
:global Identity [ / system identity get name ];
# read input from user
:global Read do={
:return;
}
# url encoding
:global UrlEncode do={
:local Input [ :tostr $1 ];
:local Return "";
:if ([ :len $Input ] > 0) do={
:local Chars " %&";
:local Subs { "%20"; "%25"; "%26" };
: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 ];
:if ($ReplaceFrom = "") do={
:return $String;
}
:while ($String ~ $ReplaceFrom) do={
:local Pos [ :find $String $ReplaceFrom ];
:set String ([ :pick $String 0 $Pos ] . $ReplaceWith . [ :pick $String ($Pos + $Len) 999 ]);
}
:return $String;
}
# check and import required certificates
:global CertificateAvailable do={
:local CommonName [ :tostr $1 ];
:local FileName ([ :tostr $2 ] . ".pem");
:global ScriptUpdatesBaseUrl;
:global ScriptUpdatesUrlSuffix;
:if ([ / certificate print count-only where common-name=$CommonName ] = 0) do={
:log info ("Certificate with CommonName " . $CommonName . \
" not available, downloading and importing.");
:do {
/ tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . "certs/" . \
$FileName . $ScriptUpdatesUrlSuffix) \
dst-path=$FileName;
/ certificate import file-name=$FileName passphrase="";
} 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" "godaddy";
: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" "letsencrypt";
:set Vendor ([ / tool fetch mode=https 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;
: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" "letsencrypt";
:do {
/ tool fetch mode=https check-certificate=yes-without-crl \
("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile) \
dst-path=$PkgDest;
} on-error={
/ file remove [ find where name=$PkgDest ];
:return false;
}
# Fetch tool in RouterOS has an issue where it truncates files on slow
# storage. Detect that... TODO: Remove when fixed. (Ticket#2019021122006199)
:if ([ / file get [ find where name=$PkgDest ] type ] != "package") do={
/ file remove [ find where name=$PkgDest ];
:return false;
}
:return true;
}