#!rsc # RouterOS script: script-updates # Copyright (c) 2013-2019 Christian Hesse # # update installed scripts from file or url :global ExpectedConfigVersion; :global GlobalConfigVersion; :global Identity; :global SentConfigChangesNotification; :global ScriptUpdatesFetch; :global ScriptUpdatesBaseUrl; :global ScriptUpdatesUrlSuffix; :global ScriptUpdatesIgnore; :global ScriptUpdatesConfigChangesIgnore; :global SendNotification; :foreach Script in=[ / system script find ] do={ :local Ignore 0; :local ScriptVal [ / system script get $Script ]; :local ScriptFile [ / file find where name=("script-updates/" . $ScriptVal->"name") ]; :local SourceNew; :if ([ :len $ScriptFile ] > 0) do={ :set SourceNew [ / file get $ScriptFile content ]; / file remove $ScriptFile; } :foreach Scheduler in=[ / system scheduler find where on-event=($ScriptVal->"name") ] do={ :local SchedulerVal [ / system scheduler get $Scheduler ]; :if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={ :log warning ("Policies differ for script " . $ScriptVal->"name" . \ " and its scheduler " . $SchedulerVal->"name" . "!"); } } :if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={ :foreach IgnoreLoop in=$ScriptUpdatesIgnore do={ :if ($IgnoreLoop = $ScriptVal->"name") do={ :set Ignore 1; } } :if ($Ignore = 0) do={ :log debug ("Fetching script from url: " . $ScriptVal->"name"); :do { :local Result [ / tool fetch check-certificate=yes-without-crl \ ($ScriptUpdatesBaseUrl . $ScriptVal->"name" . $ScriptUpdatesUrlSuffix) \ output=user as-value ]; :if ($Result->"status" = "finished") do={ :set SourceNew ($Result->"data"); } } on-error={ :log info ("Failed fetching " . $ScriptVal->"name"); } } } :if ([ :len $SourceNew ] > 0) do={ :if ([ :pick $SourceNew 0 5 ] = "#!rsc") do={ :if ($SourceNew != $ScriptVal->"source") do={ :local DontRequirePermissions \ ($SourceNew~"\n# requires: dont-require-permissions=yes\n"); :log info ("Updating script: " . $ScriptVal->"name"); / system script set owner=($ScriptVal->"name") source=$SourceNew \ dont-require-permissions=$DontRequirePermissions $Script; :if ($ScriptVal->"name" = "global-functions") do={ / system script run global-functions; } } else={ :log debug ("Script " . $ScriptVal->"name" . " did not change."); } } else={ :log warning ("Looks like new script " . $ScriptVal->"name" . " is not valid. Ignoring!"); } } else={ :log debug ("No update for script " . $ScriptVal->"name" . "."); } } :if ($ScriptUpdatesConfigChangesIgnore!=true && \ $SentConfigChangesNotification!=$ExpectedConfigVersion && \ $GlobalConfigVersion < $ExpectedConfigVersion) do={ :global GlobalConfigChanges; :local ChangeLogCode; :local Changes; :log debug ("Fetching changelog."); :do { :local Result [ / tool fetch check-certificate=yes-without-crl \ ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix) \ output=user as-value ]; :if ($Result->"status" = "finished") do={ :set ChangeLogCode ($Result->"data"); } } on-error={ :log info ("Failed fetching changes!"); } [ :parse $ChangeLogCode ]; :for I from=($GlobalConfigVersion + 1) to=$ExpectedConfigVersion do={ :set Changes ( $Changes . "\n * " . $GlobalConfigChanges->[ :tostr $I ] ); } :set GlobalConfigChanges; $SendNotification "Configuration warning!" \ ("Current configuration on " . $Identity . " is out of date. " . \ "Please update global-config, then increase variable " . \ "GlobalConfigVersion (currently " . $GlobalConfigVersion . \ ") to " . $ExpectedConfigVersion . " and re-run global-config.\n\n" . \ "Changes:" . $Changes); :set SentConfigChangesNotification $ExpectedConfigVersion; }