From 3c30276e235b6c8105f44db49ba6586d296f264c Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 25 Mar 2025 17:54:09 +0100 Subject: [PATCH] check-routeros-update: split off check-perpetual-license... ... and also add documentation, screenshot, etc. --- README.md | 1 + check-perpetual-license.rsc | 78 ++++++++++++++++++ check-routeros-update.rsc | 38 --------- .../notification.avif | Bin 0 -> 4004 bytes doc/check-perpetual-license.md | 70 ++++++++++++++++ doc/check-routeros-update.md | 1 + global-functions.rsc | 2 +- news-and-changes.rsc | 1 + 8 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 check-perpetual-license.rsc create mode 100644 doc/check-perpetual-license.d/notification.avif create mode 100644 doc/check-perpetual-license.md diff --git a/README.md b/README.md index fae6986..ffbc27e 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ Available scripts * [Renew certificates and notify on expiration](doc/check-certificates.md) * [Notify about health state](doc/check-health.md) * [Notify on LTE firmware upgrade](doc/check-lte-firmware-upgrade.md) +* [Check perpetual license on CHR](doc/check-perpetual-license.md) * [Notify on RouterOS update](doc/check-routeros-update.md) * [Collect MAC addresses in wireless access list](doc/collect-wireless-mac.md) * [Use wireless network with daily psk](doc/daily-psk.md) diff --git a/check-perpetual-license.rsc b/check-perpetual-license.rsc new file mode 100644 index 0000000..9a3a3c7 --- /dev/null +++ b/check-perpetual-license.rsc @@ -0,0 +1,78 @@ +#!rsc by RouterOS +# RouterOS script: check-perpetual-license +# Copyright (c) 2025 Christian Hesse +# https://rsc.eworm.de/COPYING.md +# +# requires RouterOS, version=7.15 +# +# check perpetual license on CHR +# https://rsc.eworm.de/doc/check-perpetual-license.md + +:global GlobalFunctionsReady; +:while ($GlobalFunctionsReady != true) do={ :delay 500ms; } + +:local ExitOK false; +:do { + :local ScriptName [ :jobname ]; + + :global Identity; + :global SentCertificateNotification; + + :global LogPrint; + :global ScriptLock; + :global SendNotification2; + :global SymbolForNotification; + :global WaitFullyConnected; + + :if ([ $ScriptLock $ScriptName ] = false) do={ + :set ExitOK true; + :error false; + } + + $WaitFullyConnected; + + :local License [ /system/license/get ]; + :if ([ :typeof ($License->"deadline-at") ] != "str") do={ + $LogPrint info $ScriptName ("This device does not have a perpetual license."); + :set ExitOK true; + :error true; + } + + :if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={ + $LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!"); + :if ($SentCertificateNotification != "expired") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ + message=("Your license expired on " . ($License->"deadline-at") . \ + ", can no longer update RouterOS on " . $Identity . "...") }); + :set SentCertificateNotification "expired"; + } + :set ExitOK true; + :error true; + } + + :if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={ + $LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!"); + :if ($SentCertificateNotification != "warning") do={ + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ + message=("Your license failed to renew and is about to expire on " . \ + ($License->"deadline-at") . " on " . $Identity . "...") }); + :set SentCertificateNotification "warning"; + } + :set ExitOK true; + :error true; + } + + :if ([ :typeof $SentCertificateNotification ] = "str" && \ + [ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={ + $LogPrint info $ScriptName ("Your license was successfully renewed."); + $SendNotification2 ({ origin=$ScriptName; \ + subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \ + message=("Your license was successfully renewed on " . $Identity . \ + ". It is now valid until " . ($License->"deadline-at") . ".") }); + :set SentCertificateNotification; + } +} on-error={ + :global ExitError; $ExitError $ExitOK [ :jobname ]; +} diff --git a/check-routeros-update.rsc b/check-routeros-update.rsc index 1a5a930..361be34 100644 --- a/check-routeros-update.rsc +++ b/check-routeros-update.rsc @@ -22,7 +22,6 @@ :global SafeUpdateNeighborIdentity; :global SafeUpdatePatch; :global SafeUpdateUrl; - :global SentCertificateNotification; :global SentRouterosUpdateNotification; :global DeviceInfo; @@ -67,43 +66,6 @@ :error "A reboot for update is already scheduled."; } - :local License [ /system/license/get ]; - :if ([ :typeof ($License->"deadline-at") ] = "str") do={ - :if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={ - $LogPrint warning $ScriptName ("Your license expired on " . ($License->"deadline-at") . "!"); - :if ($SentCertificateNotification != "expired") do={ - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License expired!"); \ - message=("Your license expired on " . ($License->"deadline-at") . \ - ", can no longer update RouterOS on " . $Identity . "...") }); - :set SentCertificateNotification "expired"; - } - :set ExitOK true; - :error false; - } - - :if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={ - $LogPrint warning $ScriptName ("Your license will expire on " . ($License->"deadline-at") . "!"); - :if ($SentCertificateNotification != "warning") do={ - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "warning-sign" ] . "License about to expire!"); \ - message=("Your license failed to renew and is about to expire on " . \ - ($License->"deadline-at") . " on " . $Identity . "...") }); - :set SentCertificateNotification "warning"; - } - } - - :if ([ :typeof $SentCertificateNotification ] = "str" && \ - [ :totime ($License->"deadline-at") ] - 4w > [ :timestamp ]) do={ - $LogPrint info $ScriptName ("Your license was successfully renewed."); - $SendNotification2 ({ origin=$ScriptName; \ - subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "License renewed"); \ - message=("Your license was successfully renewed on " . $Identity . \ - ". It is now valid until " . ($License->"deadline-at") . ".") }); - :set SentCertificateNotification; - } - } - $LogPrint debug $ScriptName ("Checking for updates..."); /system/package/update/check-for-updates without-paging as-value; :local Update [ /system/package/update/get ]; diff --git a/doc/check-perpetual-license.d/notification.avif b/doc/check-perpetual-license.d/notification.avif new file mode 100644 index 0000000000000000000000000000000000000000..70ca603d4488773dd8a476ced8c89506407b95ef GIT binary patch literal 4004 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 literal 0 HcmV?d00001 diff --git a/doc/check-perpetual-license.md b/doc/check-perpetual-license.md new file mode 100644 index 0000000..d444004 --- /dev/null +++ b/doc/check-perpetual-license.md @@ -0,0 +1,70 @@ +Check perpetual license on CHR +============================== + +[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network) +[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers) +[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.15-yellow?style=flat)](https://mikrotik.com/download/changelogs/) +[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts) +[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J) + +[⬅️ Go back to main README](../README.md) + +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. + +Description +----------- + +On *Cloud Hosted Router* (*CHR*) the licensing is perpetual: Buy once, use +forever - but it needs regular renewal. This script checks licensing state +and sends a notification to warn before expiration. + +### Sample notification + +![check-perpetual-license notification](check-perpetual-license.d/notification.avif) + +Requirements and installation +----------------------------- + +Just install the script: + + $ScriptInstallUpdate check-perpetual-license; + +And add a scheduler for automatic update notification: + + /system/scheduler/add interval=1d name=check-perpetual-license on-event="/system/script/run check-perpetual-license;" start-time=startup; + +Configuration +------------- + +No extra configuration is required for this script, but notification +settings are required for +[e-mail](mod/notification-email.md), +[matrix](mod/notification-matrix.md), +[ntfy](mod/notification-ntfy.md) and/or +[telegram](mod/notification-telegram.md). + +Usage and invocation +-------------------- + +Be notified when run from scheduler or run it manually: + + /system/script/run check-perpetual-license; + +Tips & Tricks +------------- + +The script checks for full connectivity before acting, so scheduling at +startup is perfectly valid: + + /system/scheduler/add name=check-perpetual-license@startup on-event="/system/script/run check-perpetual-license;" start-time=startup; + +See also +-------- + +* [Notify on RouterOS update](check-routeros-update.md) + +--- +[⬅️ Go back to main README](../README.md) +[⬆️ Go back to top](#top) diff --git a/doc/check-routeros-update.md b/doc/check-routeros-update.md index 926b4aa..b6c716c 100644 --- a/doc/check-routeros-update.md +++ b/doc/check-routeros-update.md @@ -99,6 +99,7 @@ startup is perfectly valid: See also -------- +* [Check perpetual license on CHR](check-perpetual-license.md) * [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md) * [Manage system update](packages-update.md) diff --git a/global-functions.rsc b/global-functions.rsc index 8ae7bb8..8ade79b 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -15,7 +15,7 @@ # Git commit id & info, expected configuration version :global CommitId "unknown"; :global CommitInfo "unknown"; -:global ExpectedConfigVersion 135; +:global ExpectedConfigVersion 136; # global variables not to be changed by user :global GlobalFunctionsReady false; diff --git a/news-and-changes.rsc b/news-and-changes.rsc index 459326f..55b4165 100644 --- a/news-and-changes.rsc +++ b/news-and-changes.rsc @@ -60,6 +60,7 @@ 133="Updated the default configuration for 'fw-addr-lists', deprecated lists were removed, a collective list was added."; 134="Enhanced 'mod/notification-telegram' and 'telegram-chat' to support topics in groups."; 135="Introduced helper function '\$GetTelegramChatId' for 'mod/notification-telegram' which helps retrieve information."; + 136="Introduced script 'check-perpetual-license' to check for license state on CHR."; }; # Migration steps to be applied on script updates